<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "XercesDOMException.hpp"

#include <cassert>

XALAN_CPP_NAMESPACE_BEGIN

template<class ExceptionType>
static XercesDOMException::ExceptionCode
translateErrorCode(ExceptionType	theException)
{
	XercesDOMException::ExceptionCode	theXalanCode = XercesDOMException::UNKNOWN_ERR;

	switch(theException.code)
	{
	case ExceptionType::INDEX_SIZE_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::DOMSTRING_SIZE_ERR:
		theXalanCode = XercesDOMException::DOMSTRING_SIZE_ERR;
		break;

	case ExceptionType::HIERARCHY_REQUEST_ERR:
		theXalanCode = XercesDOMException::HIERARCHY_REQUEST_ERR;
		break;

	case ExceptionType::WRONG_DOCUMENT_ERR:
		theXalanCode = XercesDOMException::WRONG_DOCUMENT_ERR;
		break;

	case ExceptionType::INVALID_CHARACTER_ERR:
		theXalanCode = XercesDOMException::INVALID_CHARACTER_ERR;
		break;

	case ExceptionType::NO_DATA_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_DATA_ALLOWED_ERR;
		break;

	case ExceptionType::NO_MODIFICATION_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_MODIFICATION_ALLOWED_ERR;
		break;

	case ExceptionType::NOT_FOUND_ERR:
		theXalanCode = XercesDOMException::NOT_FOUND_ERR;
		break;

	case ExceptionType::NOT_SUPPORTED_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::INUSE_ATTRIBUTE_ERR:
		theXalanCode = XercesDOMException::INUSE_ATTRIBUTE_ERR;
		break;

	case ExceptionType::INVALID_STATE_ERR:
		theXalanCode = XercesDOMException::INVALID_STATE_ERR;
		break;

	case ExceptionType::SYNTAX_ERR:
		theXalanCode = XercesDOMException::SYNTAX_ERR;
		break;

	case ExceptionType::INVALID_MODIFICATION_ERR:
		theXalanCode = XercesDOMException::INVALID_MODIFICATION_ERR;
		break;

	case ExceptionType::NAMESPACE_ERR:
		theXalanCode = XercesDOMException::NAMESPACE_ERR;
		break;

	case ExceptionType::INVALID_ACCESS_ERR:
		theXalanCode = XercesDOMException::INVALID_ACCESS_ERR;
		break;

	default:
		assert(false);
		break;
	};

	return theXalanCode;
}

XercesDOMException::XercesDOMException(ExceptionCode 	code) :
	XalanDOMException(code)
{
}

XercesDOMException::XercesDOMException(const DOM_DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}

#if XERCES_VERSION_MAJOR >= 2
XercesDOMException::XercesDOMException(const DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}
#endif

XercesDOMException::XercesDOMException(const XercesDOMException&	theSource) :
	XalanDOMException(theSource)
{
}

XercesDOMException::~XercesDOMException()
{
}

XALAN_CPP_NAMESPACE_END
<commit_msg>Work-around for the Intel v6 compiler.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "XercesDOMException.hpp"

#include <cassert>

XALAN_CPP_NAMESPACE_BEGIN

template<class ExceptionType>
static XercesDOMException::ExceptionCode
translateErrorCode(ExceptionType	theException)
{
	// Ugly hack for a bug in the Intel v6 compiler...
#if __INTEL_COMPILER <= 600
	return XercesDOMException::ExceptionCode(theException.code);
#else
	XercesDOMException::ExceptionCode	theXalanCode = XercesDOMException::UNKNOWN_ERR;

	switch(theException.code)
	{
	case ExceptionType::INDEX_SIZE_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::DOMSTRING_SIZE_ERR:
		theXalanCode = XercesDOMException::DOMSTRING_SIZE_ERR;
		break;

	case ExceptionType::HIERARCHY_REQUEST_ERR:
		theXalanCode = XercesDOMException::HIERARCHY_REQUEST_ERR;
		break;

	case ExceptionType::WRONG_DOCUMENT_ERR:
		theXalanCode = XercesDOMException::WRONG_DOCUMENT_ERR;
		break;

	case ExceptionType::INVALID_CHARACTER_ERR:
		theXalanCode = XercesDOMException::INVALID_CHARACTER_ERR;
		break;

	case ExceptionType::NO_DATA_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_DATA_ALLOWED_ERR;
		break;

	case ExceptionType::NO_MODIFICATION_ALLOWED_ERR:
		theXalanCode = XercesDOMException::NO_MODIFICATION_ALLOWED_ERR;
		break;

	case ExceptionType::NOT_FOUND_ERR:
		theXalanCode = XercesDOMException::NOT_FOUND_ERR;
		break;

	case ExceptionType::NOT_SUPPORTED_ERR:
		theXalanCode = XercesDOMException::INDEX_SIZE_ERR;
		break;

	case ExceptionType::INUSE_ATTRIBUTE_ERR:
		theXalanCode = XercesDOMException::INUSE_ATTRIBUTE_ERR;
		break;

	case ExceptionType::INVALID_STATE_ERR:
		theXalanCode = XercesDOMException::INVALID_STATE_ERR;
		break;

	case ExceptionType::SYNTAX_ERR:
		theXalanCode = XercesDOMException::SYNTAX_ERR;
		break;

	case ExceptionType::INVALID_MODIFICATION_ERR:
		theXalanCode = XercesDOMException::INVALID_MODIFICATION_ERR;
		break;

	case ExceptionType::NAMESPACE_ERR:
		theXalanCode = XercesDOMException::NAMESPACE_ERR;
		break;

	case ExceptionType::INVALID_ACCESS_ERR:
		theXalanCode = XercesDOMException::INVALID_ACCESS_ERR;
		break;

	default:
		assert(false);
		break;
	};

	return theXalanCode;
#endif
}

XercesDOMException::XercesDOMException(ExceptionCode 	code) :
	XalanDOMException(code)
{
}

XercesDOMException::XercesDOMException(const DOM_DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}

#if XERCES_VERSION_MAJOR >= 2
XercesDOMException::XercesDOMException(const DOMExceptionType&	theException) :
	XalanDOMException(translateErrorCode(theException))
{
}
#endif

XercesDOMException::XercesDOMException(const XercesDOMException&	theSource) :
	XalanDOMException(theSource)
{
}

XercesDOMException::~XercesDOMException()
{
}

XALAN_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>#define HAS_HTTP_CLIENT_LOG
#include <boost/thread.hpp>
#include "asynchttpclient.h"
#include "synchttpclient.h"

boost::asio::io_service g_io_service;

void handle_response(const ResponseInfo& r)
{
    if (r.timeout)
    {
        std::cout << "timeout" << std::endl;
    }
    else if (!r.error_msg.empty())
    {
        std::cout << r.error_msg.c_str() << std::endl;
    }
    else if (-1 == r.status_code)
    {
        std::cout << "unknown error" << std::endl;
    }
    else
    {
        std::cout << "response size=" << r.content.size()
            << ", content:\r\n" << r.content.c_str() << std::endl;
    }
}

void r_cb(boost::shared_ptr<CAsyncHttpClient>& pClient, const ResponseInfo& r)
{
    handle_response(r);
}

void f()
{
    while (1)
    {
        RequestInfo req;
        req.set_url("http://www.baidu.com/123");
        req.set_method(METHOD_GET);
        boost::shared_ptr<CAsyncHttpClient> pClient = boost::make_shared<CAsyncHttpClient>(boost::ref(g_io_service), 5);
        pClient->make_request(req, boost::bind(r_cb, pClient, _1));
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

void test_sync()
{
    RequestInfo req;
    req.set_url("http://www.baidu.com/123");
    req.set_method(METHOD_GET);
    CSyncHttpClient client(5);
    handle_response(client.make_request(req));
}

void test_async()
{
    boost::thread t(f);
    {
        boost::asio::io_service::work work(g_io_service);
        g_io_service.run();
    }
}

int main()
{
    test_async();
    return 0;
}

<commit_msg>modify test<commit_after>#define HAS_HTTP_CLIENT_LOG
#include <boost/thread.hpp>
#include "asynchttpclient.h"
#include "synchttpclient.h"

boost::asio::io_service g_io_service;

void handle_response(const ResponseInfo& r)
{
    if (r.timeout)
    {
        std::cout << "timeout" << std::endl;
    }
    else if (!r.error_msg.empty())
    {
        std::cout << r.error_msg.c_str() << std::endl;
    }
    else if (-1 == r.status_code)
    {
        std::cout << "unknown error" << std::endl;
    }
    else
    {
        std::cout << "response size=" << r.content.size()
            << ", content:\r\n" << r.content.c_str() << std::endl;
    }
}

void r_cb(boost::shared_ptr<CAsyncHttpClient>& pClient, const ResponseInfo& r)
{
    handle_response(r);
}

void f()
{
    while (true)
    {
        RequestInfo req;
        req.set_url("http://www.baidu.com/123");
        req.set_method(METHOD_GET);
        boost::shared_ptr<CAsyncHttpClient> pClient = boost::make_shared<CAsyncHttpClient>(boost::ref(g_io_service), 5);
        pClient->make_request(req, boost::bind(r_cb, pClient, _1));
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

void test_sync()
{
    while (true)
    {
        RequestInfo req;
        req.set_url("http://www.baidu.com/123");
        req.set_method(METHOD_GET);
        CSyncHttpClient client(5);
        handle_response(client.make_request(req));
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

void test_async()
{
    boost::thread t(f);
    {
        boost::asio::io_service::work work(g_io_service);
        g_io_service.run();
    }
}

int main()
{
    test_async();
    return 0;
}

<|endoftext|>


<commit_before>//
// Created by dar on 11/28/15.
//

#include "DefaultEntityRender.h"
#include "../../core/map/block/Block.h"
#include <string>

DefaultEntityRender::DefaultEntityRender(const string &textureFile, const string &shader) {
    texture.loadTexture2D(textureFile + string(".png"), false);
    texture.setFiltering(TEXTURE_FILTER_MAG_NEAREST, TEXTURE_FILTER_MIN_NEAREST);

    int a = this->vertShader.load(shader + string(".vert"), GL_VERTEX_SHADER);
    int b = this->fragShader.load(shader + string(".frag"), GL_FRAGMENT_SHADER);

    this->shaderProgram.createProgram();
    this->shaderProgram.addShaderToProgram(&this->vertShader);
    this->shaderProgram.addShaderToProgram(&this->fragShader);

    /* initializing square's vertices */
    this->vertices[0] = 0.0f;
    this->vertices[1] = 1.0f;

    this->vertices[3] = 0.0f;
    this->vertices[4] = 0.0f;

    this->vertices[6] = 1.0f;
    this->vertices[7] = 1.0f;

    this->vertices[9] = 1.0f;
    this->vertices[10] = 0.0f;

    /* 3rd dimension vertices (unused) */
    this->vertices[2] = this->vertices[5] = this->vertices[8] = this->vertices[11] = 0.0f;

    glGenVertexArrays(1, &this->vao);
    glGenBuffers(2, this->vbo);

    glBindVertexArray(this->vao);

    glBindBuffer(GL_ARRAY_BUFFER, this->vbo[0]); /* vertices vbo */
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), this->vertices, GL_STATIC_DRAW);
    glBindAttribLocation(this->shaderProgram.getProgramID(), 0, "inPosition");
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    float size = (float) (1.0 - (atlasSize + 1.5) / texture.getWidth()) / atlasSize;
    float tCoords[] = {
        size, 0.0f,
        size, size,
        0.0f, 0.0f,
        0.0f, size,
    };

    glBindBuffer(GL_ARRAY_BUFFER, this->vbo[1]); /* texture coords vbo */
    glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), tCoords, GL_STATIC_DRAW);
    glBindAttribLocation(this->shaderProgram.getProgramID(), 1, "inCoord");
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);

    this->shaderProgram.linkProgram();
    this->shaderProgram.useProgram();
}

void DefaultEntityRender::render(const Entity *const entity, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, double scale) {
    this->texture.bindTexture(0);
    this->shaderProgram.useProgram();
    this->shaderProgram.setUniform("projectionMatrix", projectionMatrix);
    this->shaderProgram.setUniform("gSampler", texture.getBoundId());

    this->tmpModelMatrix = glm::translate(this->modelMatrix, glm::vec3(0.0f - (entity->getX() - entity->getWidth() / 2) * scale, 0.0f - (entity->getY() - entity->getHeight() / 2) * scale, 0.0f));

    this->tmpModelMatrix = glm::translate(this->tmpModelMatrix, glm::vec3(0.5 * scale, 0.5 * scale, 0.0)); // Translate to the middle of the entity
    this->tmpModelMatrix = glm::rotate(this->tmpModelMatrix, (const float) entity->getAngle(), glm::vec3(0.0f, 0.0f, 1.0f)); // Apply rotation
    this->tmpModelMatrix = glm::translate(this->tmpModelMatrix, glm::vec3(-0.5 * scale, -0.5 * scale, 0.0)); // Translate back to the origin

    this->tmpModelMatrix = glm::scale(this->tmpModelMatrix, glm::vec3(scale, scale, 1.0f));

    shaderProgram.setUniform("modelViewMatrix", viewMatrix * this->tmpModelMatrix);
    shaderProgram.setUniform("texPosX", 1.0f / this->texture.getWidth() + (float) (this->getTexPos() % atlasSize) / atlasSize);
    shaderProgram.setUniform("texPosY", 1.0f / this->texture.getWidth() + (float) (this->getTexPos() / atlasSize) / atlasSize);

    glBindVertexArray(this->vao);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

int DefaultEntityRender::getTexPos() {
    return 0;
}

DefaultEntityRender::~DefaultEntityRender() {
    glDeleteBuffers(2, this->vbo);
    glDeleteVertexArrays(1, &this->vao);
}
<commit_msg>Change entities texture filtering to BILLINEAR_MIPMAP<commit_after>//
// Created by dar on 11/28/15.
//

#include "DefaultEntityRender.h"
#include "../../core/map/block/Block.h"
#include <string>

DefaultEntityRender::DefaultEntityRender(const string &textureFile, const string &shader) {
    texture.loadTexture2D(textureFile + string(".png"), true);
    texture.setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);

    int a = this->vertShader.load(shader + string(".vert"), GL_VERTEX_SHADER);
    int b = this->fragShader.load(shader + string(".frag"), GL_FRAGMENT_SHADER);

    this->shaderProgram.createProgram();
    this->shaderProgram.addShaderToProgram(&this->vertShader);
    this->shaderProgram.addShaderToProgram(&this->fragShader);

    /* initializing square's vertices */
    this->vertices[0] = 0.0f;
    this->vertices[1] = 1.0f;

    this->vertices[3] = 0.0f;
    this->vertices[4] = 0.0f;

    this->vertices[6] = 1.0f;
    this->vertices[7] = 1.0f;

    this->vertices[9] = 1.0f;
    this->vertices[10] = 0.0f;

    /* 3rd dimension vertices (unused) */
    this->vertices[2] = this->vertices[5] = this->vertices[8] = this->vertices[11] = 0.0f;

    glGenVertexArrays(1, &this->vao);
    glGenBuffers(2, this->vbo);

    glBindVertexArray(this->vao);

    glBindBuffer(GL_ARRAY_BUFFER, this->vbo[0]); /* vertices vbo */
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), this->vertices, GL_STATIC_DRAW);
    glBindAttribLocation(this->shaderProgram.getProgramID(), 0, "inPosition");
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    float size = (float) (1.0 - (atlasSize + 1.5) / texture.getWidth()) / atlasSize;
    float tCoords[] = {
        size, 0.0f,
        size, size,
        0.0f, 0.0f,
        0.0f, size,
    };

    glBindBuffer(GL_ARRAY_BUFFER, this->vbo[1]); /* texture coords vbo */
    glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), tCoords, GL_STATIC_DRAW);
    glBindAttribLocation(this->shaderProgram.getProgramID(), 1, "inCoord");
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);

    this->shaderProgram.linkProgram();
    this->shaderProgram.useProgram();
}

void DefaultEntityRender::render(const Entity *const entity, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, double scale) {
    this->texture.bindTexture(0);
    this->shaderProgram.useProgram();
    this->shaderProgram.setUniform("projectionMatrix", projectionMatrix);
    this->shaderProgram.setUniform("gSampler", texture.getBoundId());

    this->tmpModelMatrix = glm::translate(this->modelMatrix, glm::vec3(0.0f - (entity->getX() - entity->getWidth() / 2) * scale, 0.0f - (entity->getY() - entity->getHeight() / 2) * scale, 0.0f));

    this->tmpModelMatrix = glm::translate(this->tmpModelMatrix, glm::vec3(0.5 * scale, 0.5 * scale, 0.0)); // Translate to the middle of the entity
    this->tmpModelMatrix = glm::rotate(this->tmpModelMatrix, (const float) entity->getAngle(), glm::vec3(0.0f, 0.0f, 1.0f)); // Apply rotation
    this->tmpModelMatrix = glm::translate(this->tmpModelMatrix, glm::vec3(-0.5 * scale, -0.5 * scale, 0.0)); // Translate back to the origin

    this->tmpModelMatrix = glm::scale(this->tmpModelMatrix, glm::vec3(scale, scale, 1.0f));

    shaderProgram.setUniform("modelViewMatrix", viewMatrix * this->tmpModelMatrix);
    shaderProgram.setUniform("texPosX", 1.0f / this->texture.getWidth() + (float) (this->getTexPos() % atlasSize) / atlasSize);
    shaderProgram.setUniform("texPosY", 1.0f / this->texture.getWidth() + (float) (this->getTexPos() / atlasSize) / atlasSize);

    glBindVertexArray(this->vao);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

int DefaultEntityRender::getTexPos() {
    return 0;
}

DefaultEntityRender::~DefaultEntityRender() {
    glDeleteBuffers(2, this->vbo);
    glDeleteVertexArrays(1, &this->vao);
}
<|endoftext|>


<commit_before>#include <dune/stuff/test/test_common.hh>

#if HAVE_ALUGRID

#include <vector>

#include <dune/grid/alugrid.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/grid/provider.hh>

#include <dune/detailed/discretizations/space/lagrange-continuous.hh>
#include <dune/detailed/discretizations/mapper/interface.hh>
#include <dune/detailed/discretizations/basefunctionset/interface.hh>

namespace Stuff = Dune::Stuff;
namespace DD    = Dune::Detailed::Discretizations;

static const unsigned int dimDomain = 2;
typedef Dune::ALUGrid<dimDomain, dimDomain, Dune::simplex, Dune::conforming> GridType;
typedef typename GridType::ctype DomainFieldType;
typedef double RangeFieldType;
static const unsigned int dimRange = 1;
typedef Dune::grid::Part::Leaf::Const<GridType> GridPartType;

typedef testing::Types<DD::ContinuousLagrangeSpace<GridPartType, RangeFieldType, dimRange, 1>> SpaceTypes;

template <class T>
struct SpaceCRTPtest : public ::testing::Test
{
  typedef T SpaceType;

  void check(const GridPartType& gridPart) const
  {
    // check the space
    const SpaceType space(gridPart);
    // check for static information
    typedef typename SpaceType::Traits Traits;
    typedef typename SpaceType::GridPartType S_GridPartType;
    typedef typename SpaceType::DomainFieldType S_DomainFieldType;
    static const unsigned int DUNE_UNUSED(s_dimDomain) = SpaceType::dimDomain;
    typedef typename SpaceType::RangeFieldType S_RangeFieldType;
    static const unsigned int DUNE_UNUSED(s_dimRange) = SpaceType::dimRange;
    static const int DUNE_UNUSED(s_polOrder) = SpaceType::polOrder;
    typedef typename SpaceType::BackendType S_BackendType;
    typedef typename SpaceType::MapperType MapperType;
    typedef typename SpaceType::BaseFunctionSetType BaseFunctionSetType;
    typedef typename SpaceType::EntityType EntityType;
    // check for functionality
    const auto entityIt      = gridPart.template begin<0>();
    const EntityType& entity = *entityIt;
    typedef typename DD::SpaceInterface<Traits> SpaceInterfaceType;
    const SpaceInterfaceType& spaceAsInterface = static_cast<const SpaceInterfaceType&>(space);
    const S_GridPartType& DUNE_UNUSED(s_gridPart) = spaceAsInterface.gridPart();
    const S_BackendType& DUNE_UNUSED(s_backend) = spaceAsInterface.backend();
    const bool DUNE_UNUSED(s_continuous) = spaceAsInterface.continuous();
    const MapperType& mapper                  = spaceAsInterface.mapper();
    const BaseFunctionSetType baseFunctionSet = spaceAsInterface.baseFunctionSet(entity);

    // check the mapper for static information
    typedef typename MapperType::Traits M_Traits;
    typedef typename M_Traits::BackendType M_BackendType;
    typedef typename M_Traits::SpaceType M_SpaceType;
    typedef typename M_Traits::IndexType M_IndexType;
    // check the mapper for functionality
    typedef DD::Mapper::Interface<M_Traits> MapperInterfaceType;
    const MapperInterfaceType& mapperAsInterface = static_cast<const MapperInterfaceType&>(mapper);
    const M_SpaceType& DUNE_UNUSED(m_space) = mapperAsInterface.space();
    const M_BackendType& DUNE_UNUSED(m_backend) = mapperAsInterface.backend();
    const M_IndexType m_maxNumDofs = mapperAsInterface.maxNumDofs();
    const M_IndexType DUNE_UNUSED(m_numDofs) = mapperAsInterface.numDofs(entity);
    Dune::DynamicVector<M_IndexType> globalIndices(m_maxNumDofs, M_IndexType(0));
    mapperAsInterface.mapToGlobal(entity, globalIndices);
    const M_IndexType DUNE_UNUSED(globalIndex) = mapperAsInterface.mapToGlobal(entity, 0);

    // check the basefunctionset for static information
    typedef typename BaseFunctionSetType::Traits B_Traits;
    typedef typename B_Traits::SpaceType B_SpaceType;
    typedef typename B_Traits::BackendType B_BackendType;
    typedef typename B_Traits::IndexType B_IndexType;
    typedef typename B_Traits::EntityType B_EntityType;
    typedef typename B_Traits::DomainType B_DomainType;
    typedef typename B_Traits::RangeType B_RangeType;
    typedef typename B_Traits::JacobianRangeType B_JacobianRangeType;
    // check the basefunctionset for functionality
    typedef DD::BaseFunctionSet::Interface<B_Traits> BaseFunctionSetInterfaceType;
    const BaseFunctionSetInterfaceType& baseFunctionSetAsInterface =
        static_cast<const BaseFunctionSetInterfaceType&>(baseFunctionSet);
    const B_SpaceType& DUNE_UNUSED(b_space) = baseFunctionSetAsInterface.space();
    const B_EntityType& DUNE_UNUSED(b_entity) = baseFunctionSetAsInterface.entity();
    const B_BackendType& DUNE_UNUSED(b_backend) = baseFunctionSetAsInterface.backend();
    const B_IndexType b_size = baseFunctionSetAsInterface.size();
    const unsigned int DUNE_UNUSED(b_order) = baseFunctionSetAsInterface.order();
    const B_DomainType x = entity.geometry().center();
    std::vector<B_RangeType> values(b_size, B_RangeType(0));
    std::vector<B_JacobianRangeType> jacobians(b_size, B_JacobianRangeType(0));
    baseFunctionSetAsInterface.evaluate(x, values);
    baseFunctionSetAsInterface.jacobian(x, jacobians);
  } // ... check()
}; // struct SpaceCRTPtest

TYPED_TEST_CASE(SpaceCRTPtest, SpaceTypes);
TYPED_TEST(SpaceCRTPtest, SpaceCRTP)
{
  const Stuff::GridProviderInterface<GridType>* gridProvider =
      Dune::Stuff::GridProviders<GridType>::create("gridprovider.cube");
  const Dune::grid::Part::Leaf::Const<GridType> gridPart(*(gridProvider->grid()));
  this->check(gridPart);
  delete gridProvider;
}

int main(int argc, char** argv)
{
  test_init(argc, argv);
  return RUN_ALL_TESTS();
}

#else
int main(int argc, char** argv)
{
  std::cerr << "'HAVE_ALUGRID' not set!" return 1;
}
#endif // HAVE_ALUGRID
<commit_msg>[test.spaces] update<commit_after>#include <dune/stuff/test/test_common.hh>

#if HAVE_ALUGRID

#include <vector>

#include <dune/grid/alugrid.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/grid/provider.hh>

#include <dune/detailed/discretizations/space/lagrange-continuous.hh>
#include <dune/detailed/discretizations/mapper/interface.hh>
#include <dune/detailed/discretizations/basefunctionset/interface.hh>

namespace Stuff = Dune::Stuff;
namespace DD    = Dune::Detailed::Discretizations;

static const unsigned int dimDomain = 2;
typedef Dune::ALUGrid<dimDomain, dimDomain, Dune::simplex, Dune::conforming> GridType;
typedef typename GridType::ctype DomainFieldType;
typedef double RangeFieldType;
static const unsigned int dimRange = 1;
typedef Dune::grid::Part::Leaf::Const<GridType> GridPartType;

typedef testing::Types<DD::ContinuousLagrangeSpace<GridPartType, 1, RangeFieldType, dimRange>> SpaceTypes;

template <class T>
struct SpaceCRTPtest : public ::testing::Test
{
  typedef T SpaceType;

  void check(const GridPartType& gridPart) const
  {
    // check the space
    const SpaceType space(gridPart);
    // check for static information
    typedef typename SpaceType::Traits Traits;
    typedef typename SpaceType::GridPartType S_GridPartType;
    typedef typename SpaceType::DomainFieldType S_DomainFieldType;
    static const unsigned int DUNE_UNUSED(s_dimDomain) = SpaceType::dimDomain;
    typedef typename SpaceType::RangeFieldType S_RangeFieldType;
    static const unsigned int DUNE_UNUSED(s_dimRangeRows) = SpaceType::dimRangeRows;
    static const unsigned int DUNE_UNUSED(s_dimRangeCols) = SpaceType::dimRangeCols;
    static const int DUNE_UNUSED(s_polOrder) = SpaceType::polOrder;
    typedef typename SpaceType::BackendType S_BackendType;
    typedef typename SpaceType::MapperType MapperType;
    typedef typename SpaceType::BaseFunctionSetType BaseFunctionSetType;
    typedef typename SpaceType::EntityType EntityType;
    // check for functionality
    const auto entityIt      = gridPart.template begin<0>();
    const EntityType& entity = *entityIt;
    typedef typename DD::SpaceInterface<Traits> SpaceInterfaceType;
    const SpaceInterfaceType& spaceAsInterface = static_cast<const SpaceInterfaceType&>(space);
    const S_GridPartType& DUNE_UNUSED(s_gridPart) = spaceAsInterface.gridPart();
    const S_BackendType& DUNE_UNUSED(s_backend) = spaceAsInterface.backend();
    const bool DUNE_UNUSED(s_continuous) = spaceAsInterface.continuous();
    const MapperType& mapper                  = spaceAsInterface.mapper();
    const BaseFunctionSetType baseFunctionSet = spaceAsInterface.baseFunctionSet(entity);

    // check the mapper for static information
    typedef typename MapperType::Traits M_Traits;
    typedef typename M_Traits::BackendType M_BackendType;
    // check the mapper for functionality
    typedef DD::MapperInterface<M_Traits> MapperInterfaceType;
    const MapperInterfaceType& mapperAsInterface = static_cast<const MapperInterfaceType&>(mapper);
    const M_BackendType& DUNE_UNUSED(m_backend) = mapperAsInterface.backend();
    const size_t m_maxNumDofs = mapperAsInterface.maxNumDofs();
    const size_t DUNE_UNUSED(m_numDofs) = mapperAsInterface.numDofs(entity);
    Dune::DynamicVector<size_t> globalIndices(m_maxNumDofs, size_t(0));
    mapperAsInterface.mapToGlobal(entity, globalIndices);
    const size_t DUNE_UNUSED(globalIndex) = mapperAsInterface.mapToGlobal(entity, 0);

    // check the basefunctionset for static information
    typedef typename BaseFunctionSetType::Traits B_Traits;
    typedef typename B_Traits::BackendType B_BackendType;
    typedef typename B_Traits::EntityType B_EntityType;
    typedef typename B_Traits::DomainType B_DomainType;
    typedef typename B_Traits::RangeType B_RangeType;
    typedef typename B_Traits::JacobianRangeType B_JacobianRangeType;
    // check the basefunctionset for functionality
    typedef DD::BaseFunctionSetInterface<B_Traits> BaseFunctionSetInterfaceType;
    const BaseFunctionSetInterfaceType& baseFunctionSetAsInterface =
        static_cast<const BaseFunctionSetInterfaceType&>(baseFunctionSet);
    const B_EntityType& DUNE_UNUSED(b_entity) = baseFunctionSetAsInterface.entity();
    const B_BackendType& DUNE_UNUSED(b_backend) = baseFunctionSetAsInterface.backend();
    const size_t b_size = baseFunctionSetAsInterface.size();
    const unsigned int DUNE_UNUSED(b_order) = baseFunctionSetAsInterface.order();
    const B_DomainType x = entity.geometry().center();
    std::vector<B_RangeType> values(b_size, B_RangeType(0));
    std::vector<B_JacobianRangeType> jacobians(b_size, B_JacobianRangeType(0));
    baseFunctionSetAsInterface.evaluate(x, values);
    baseFunctionSetAsInterface.jacobian(x, jacobians);
  } // ... check()
}; // struct SpaceCRTPtest

TYPED_TEST_CASE(SpaceCRTPtest, SpaceTypes);
TYPED_TEST(SpaceCRTPtest, SpaceCRTP)
{
  const Stuff::GridProviderInterface<GridType>* gridProvider =
      Dune::Stuff::GridProviders<GridType>::create("gridprovider.cube");
  const Dune::grid::Part::Leaf::Const<GridType> gridPart(*(gridProvider->grid()));
  this->check(gridPart);
  delete gridProvider;
}

int main(int argc, char** argv)
{
  test_init(argc, argv);
  return RUN_ALL_TESTS();
}

#else
int main(int argc, char** argv)
{
  std::cerr << "'HAVE_ALUGRID' not set!";
  return 1;
}
#endif // HAVE_ALUGRID
<|endoftext|>


<commit_before>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2018

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RCOLUMNVALUE
#define ROOT_RCOLUMNVALUE

#include <ROOT/RDF/RCustomColumnBase.hxx>
#include <ROOT/RDF/Utils.hxx> // IsRVec_t, TypeID2TypeName
#include <ROOT/RIntegerSequence.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RVec.hxx>
#include <ROOT/TypeTraits.hxx> // TakeFirstParameter_t
#include <RtypesCore.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>

#include <cstring> // strcmp
#include <initializer_list>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {
using namespace ROOT::VecOps;

/**
\class ROOT::Internal::RDF::RColumnValue
\ingroup dataframe
\brief Helper class that updates and returns TTree branches as well as RDataFrame temporary columns
\tparam T The type of the column

RDataFrame nodes must access two different types of values during the event loop:
values of real branches, for which TTreeReader{Values,Arrays} act as proxies, or
temporary columns whose values are generated on the fly. While the type of the
value is known at compile time (or just-in-time), it is only at runtime that nodes
can check whether a certain value is generated on the fly or not.

RColumnValue abstracts this difference by providing the same interface for
both cases and handling the reading or generation of new values transparently.
Only one of the two data members fReaderProxy or fValuePtr will be non-null
for a given RColumnValue, depending on whether the value comes from a real
TTree branch or from a temporary column respectively.

RDataFrame nodes can store tuples of RColumnValues and retrieve an updated
value for the column via the `Get` method.
**/
template <typename T>
class R__CLING_PTRCHECK(off) RColumnValue {
// R__CLING_PTRCHECK is disabled because all pointers are hand-crafted by RDF.

   using MustUseRVec_t = IsRVec_t<T>;

   // ColumnValue_t is the type of the column or the type of the elements of an array column
   using ColumnValue_t = typename std::conditional<MustUseRVec_t::value, TakeFirstParameter_t<T>, T>::type;
   using TreeReader_t = typename std::conditional<MustUseRVec_t::value, TTreeReaderArray<ColumnValue_t>,
                                                  TTreeReaderValue<ColumnValue_t>>::type;

   /// RColumnValue has a slightly different behaviour whether the column comes from a TTreeReader, a RDataFrame Define
   /// or a RDataSource. It stores which it is as an enum.
   enum class EColumnKind { kTree, kCustomColumn, kDataSource, kInvalid };
   // Set to the correct value by MakeProxy or SetTmpColumn
   EColumnKind fColumnKind = EColumnKind::kInvalid;
   /// The slot this value belongs to. Only needed when querying custom column values, it is set in `SetTmpColumn`.
   unsigned int fSlot = std::numeric_limits<unsigned int>::max();

   // Each element of the following stacks will be in use by a _single task_.
   // Each task will push one element when it starts and pop it when it ends.
   // Stacks will typically be very small (1-2 elements typically) and will only grow over size 1 in case of interleaved
   // task execution i.e. when more than one task needs readers in this worker thread.

   /// Owning ptrs to a TTreeReaderValue or TTreeReaderArray. Only used for Tree columns.
   std::unique_ptr<TreeReader_t> fTreeReader;
   /// Non-owning ptrs to the value of a custom column.
   T *fCustomValuePtr;
   /// Non-owning ptrs to the value of a data-source column.
   T **fDSValuePtr;
   /// Non-owning ptrs to the node responsible for the custom column. Needed when querying custom values.
   RCustomColumnBase *fCustomColumn;
   /// Enumerator for the different properties of the branch storage in memory
   enum class EStorageType : char { kContiguous, kUnknown, kSparse };
   /// Signal whether we ever checked that the branch we are reading with a TTreeReaderArray stores array elements
   /// in contiguous memory. Only used when T == RVec<U>.
   EStorageType fStorageType = EStorageType::kUnknown;
   /// If MustUseRVec, i.e. we are reading an array, we return a reference to this RVec to clients
   RVec<ColumnValue_t> fRVec;
   bool fCopyWarningPrinted = false;

public:
   RColumnValue(){};

   void SetTmpColumn(unsigned int slot, RCustomColumnBase *customColumn)
   {
      fCustomColumn = customColumn;
      // Here we compare names and not typeinfos since they may come from two different contexts: a compiled
      // and a jitted one.
      if (0 != strcmp(customColumn->GetTypeId().name(), typeid(T).name()))
         throw std::runtime_error(
            std::string("RColumnValue: type specified for column \"" + customColumn->GetName() + "\" is ") +
            TypeID2TypeName(typeid(T)) + " but temporary column has type " +
            TypeID2TypeName(customColumn->GetTypeId()));

      if (customColumn->IsDataSourceColumn()) {
         fColumnKind = EColumnKind::kDataSource;
         fDSValuePtr = static_cast<T **>(customColumn->GetValuePtr(slot));
      } else {
         fColumnKind = EColumnKind::kCustomColumn;
         fCustomValuePtr = static_cast<T *>(customColumn->GetValuePtr(slot));
      }
      fSlot = slot;
   }

   void MakeProxy(TTreeReader *r, const std::string &bn)
   {
      fColumnKind = EColumnKind::kTree;
      fTreeReader = std::make_unique<TreeReader_t>(*r, bn.c_str());
   }

   /// This overload is used to return scalar quantities (i.e. types that are not read into a RVec)
   // This method is executed inside the event-loop, many times per entry
   // If need be, the if statement can be avoided using thunks
   // (have both branches inside functions and have a pointer to the branch to be executed)
   template <typename U = T, typename std::enable_if<!RColumnValue<U>::MustUseRVec_t::value, int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         return *(fTreeReader->Get());
      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload is used to return arrays (i.e. types that are read into a RVec).
   /// In this case the returned T is always a RVec<ColumnValue_t>.
   /// RVec<bool> is treated differently, in a separate overload.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && !std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         // We only use TTreeReaderArrays to read columns that users flagged as type `RVec`, so we need to check
         // that the branch stores the array as contiguous memory that we can actually wrap in an `RVec`.
         // Currently we need the first entry to have been loaded to perform the check
         // TODO Move check to `MakeProxy` once Axel implements this kind of check in TTreeReaderArray using
         // TBranchProxy

         if (EStorageType::kUnknown == fStorageType && readerArray.GetSize() > 1) {
            // We can decide since the array is long enough
            fStorageType =
               (1 == (&readerArray[1] - &readerArray[0])) ? EStorageType::kContiguous : EStorageType::kSparse;
         }

         const auto readerArraySize = readerArray.GetSize();
         if (EStorageType::kContiguous == fStorageType ||
             (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
            if (readerArraySize > 0) {
               // trigger loading of the contents of the TTreeReaderArray
               // the address of the first element in the reader array is not necessarily equal to
               // the address returned by the GetAddress method
               auto readerArrayAddr = &readerArray.At(0);
               T rvec(readerArrayAddr, readerArraySize);
               swap(fRVec, rvec);
            } else {
               T emptyVec{};
               swap(fRVec, emptyVec);
            }
         } else {
            // The storage is not contiguous or we don't know yet: we cannot but copy into the rvec
#ifndef NDEBUG
            if (!fCopyWarningPrinted) {
               Warning("RColumnValue::Get",
                       "Branch %s hangs from a non-split branch. A copy is being performed in order "
                       "to properly read the content.",
                       readerArray.GetBranchName());
               fCopyWarningPrinted = true;
            }
#else
            (void)fCopyWarningPrinted;
#endif
            if (readerArraySize > 0) {
               T rvec(readerArray.begin(), readerArray.end());
               swap(fRVec, rvec);
            } else {
               T emptyVec{};
               swap(fRVec, emptyVec);
            }
         }
         return fRVec;

      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload covers the RVec<bool> case. In this case we always copy the contents of TTreeReaderArray<bool>
   /// into RVec<bool> (never take a view into the memory buffer) because the underlying memory buffer might be the
   /// one of a std::vector<bool>, which is not a contiguous slab of bool values.
   /// Note that this also penalizes the case in which the column type is actually bool[], but the possible performance
   /// gains in this edge case is probably not worth the extra complication required to differentiate the two cases.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         const auto readerArraySize = readerArray.GetSize();
         if (readerArraySize > 0) {
            // always perform a copy
            T rvec(readerArray.begin(), readerArray.end());
            swap(fRVec, rvec);
         } else {
            T emptyVec{};
            swap(fRVec, emptyVec);
         }
         return fRVec;
      } else {
         // business as usual
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   void Reset()
   {
      // This method should by all means not be removed, together with all
      // of its callers, otherwise a race condition takes place in which a
      // TTreeReader and its TTreeReader{Value,Array}s could be deleted
      // concurrently:
      // - Thread #1) a task ends and pushes back processing slot
      // - Thread #2) a task starts and overwrites thread-local TTreeReaderValues
      // - Thread #1) first task deletes TTreeReader
      // See https://github.com/root-project/root/commit/26e8ace6e47de6794ac9ec770c3bbff9b7f2e945
      if (EColumnKind::kTree == fColumnKind) {
         fTreeReader.reset();
      }
   }
};

// Some extern instantiations to speed-up compilation/interpretation time
// These are not active if c++17 is enabled because of a bug in our clang
// See ROOT-9499.
#if __cplusplus < 201703L
extern template class RColumnValue<int>;
extern template class RColumnValue<unsigned int>;
extern template class RColumnValue<char>;
extern template class RColumnValue<unsigned char>;
extern template class RColumnValue<float>;
extern template class RColumnValue<double>;
extern template class RColumnValue<Long64_t>;
extern template class RColumnValue<ULong64_t>;
extern template class RColumnValue<std::vector<int>>;
extern template class RColumnValue<std::vector<unsigned int>>;
extern template class RColumnValue<std::vector<char>>;
extern template class RColumnValue<std::vector<unsigned char>>;
extern template class RColumnValue<std::vector<float>>;
extern template class RColumnValue<std::vector<double>>;
extern template class RColumnValue<std::vector<Long64_t>>;
extern template class RColumnValue<std::vector<ULong64_t>>;
#endif

template <typename T>
struct TRDFValueTuple {
};

template <typename... BranchTypes>
struct TRDFValueTuple<TypeList<BranchTypes...>> {
   using type = std::tuple<RColumnValue<BranchTypes>...>;
};

template <typename BranchType>
using RDFValueTuple_t = typename TRDFValueTuple<BranchType>::type;

/// Clear the proxies of a tuple of RColumnValues
template <typename ValueTuple, std::size_t... S>
void ResetRDFValueTuple(ValueTuple &values, std::index_sequence<S...>)
{
   // hack to expand a parameter pack without c++17 fold expressions.
   std::initializer_list<int> expander{(std::get<S>(values).Reset(), 0)...};
   (void)expander; // avoid "unused variable" warnings
}

} // ns RDF
} // ns Internal
} // ns ROOT

#endif // ROOT_RCOLUMNVALUE
<commit_msg>[RDF] Use std::swap for RVecs when reading array columns<commit_after>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2018

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RCOLUMNVALUE
#define ROOT_RCOLUMNVALUE

#include <ROOT/RDF/RCustomColumnBase.hxx>
#include <ROOT/RDF/Utils.hxx> // IsRVec_t, TypeID2TypeName
#include <ROOT/RIntegerSequence.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <ROOT/RVec.hxx>
#include <ROOT/TypeTraits.hxx> // TakeFirstParameter_t
#include <RtypesCore.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>

#include <cstring> // strcmp
#include <initializer_list>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {
using namespace ROOT::VecOps;

/**
\class ROOT::Internal::RDF::RColumnValue
\ingroup dataframe
\brief Helper class that updates and returns TTree branches as well as RDataFrame temporary columns
\tparam T The type of the column

RDataFrame nodes must access two different types of values during the event loop:
values of real branches, for which TTreeReader{Values,Arrays} act as proxies, or
temporary columns whose values are generated on the fly. While the type of the
value is known at compile time (or just-in-time), it is only at runtime that nodes
can check whether a certain value is generated on the fly or not.

RColumnValue abstracts this difference by providing the same interface for
both cases and handling the reading or generation of new values transparently.
Only one of the two data members fReaderProxy or fValuePtr will be non-null
for a given RColumnValue, depending on whether the value comes from a real
TTree branch or from a temporary column respectively.

RDataFrame nodes can store tuples of RColumnValues and retrieve an updated
value for the column via the `Get` method.
**/
template <typename T>
class R__CLING_PTRCHECK(off) RColumnValue {
// R__CLING_PTRCHECK is disabled because all pointers are hand-crafted by RDF.

   using MustUseRVec_t = IsRVec_t<T>;

   // ColumnValue_t is the type of the column or the type of the elements of an array column
   using ColumnValue_t = typename std::conditional<MustUseRVec_t::value, TakeFirstParameter_t<T>, T>::type;
   using TreeReader_t = typename std::conditional<MustUseRVec_t::value, TTreeReaderArray<ColumnValue_t>,
                                                  TTreeReaderValue<ColumnValue_t>>::type;

   /// RColumnValue has a slightly different behaviour whether the column comes from a TTreeReader, a RDataFrame Define
   /// or a RDataSource. It stores which it is as an enum.
   enum class EColumnKind { kTree, kCustomColumn, kDataSource, kInvalid };
   // Set to the correct value by MakeProxy or SetTmpColumn
   EColumnKind fColumnKind = EColumnKind::kInvalid;
   /// The slot this value belongs to. Only needed when querying custom column values, it is set in `SetTmpColumn`.
   unsigned int fSlot = std::numeric_limits<unsigned int>::max();

   // Each element of the following stacks will be in use by a _single task_.
   // Each task will push one element when it starts and pop it when it ends.
   // Stacks will typically be very small (1-2 elements typically) and will only grow over size 1 in case of interleaved
   // task execution i.e. when more than one task needs readers in this worker thread.

   /// Owning ptrs to a TTreeReaderValue or TTreeReaderArray. Only used for Tree columns.
   std::unique_ptr<TreeReader_t> fTreeReader;
   /// Non-owning ptrs to the value of a custom column.
   T *fCustomValuePtr;
   /// Non-owning ptrs to the value of a data-source column.
   T **fDSValuePtr;
   /// Non-owning ptrs to the node responsible for the custom column. Needed when querying custom values.
   RCustomColumnBase *fCustomColumn;
   /// Enumerator for the different properties of the branch storage in memory
   enum class EStorageType : char { kContiguous, kUnknown, kSparse };
   /// Signal whether we ever checked that the branch we are reading with a TTreeReaderArray stores array elements
   /// in contiguous memory. Only used when T == RVec<U>.
   EStorageType fStorageType = EStorageType::kUnknown;
   /// If MustUseRVec, i.e. we are reading an array, we return a reference to this RVec to clients
   RVec<ColumnValue_t> fRVec;
   bool fCopyWarningPrinted = false;

public:
   RColumnValue(){};

   void SetTmpColumn(unsigned int slot, RCustomColumnBase *customColumn)
   {
      fCustomColumn = customColumn;
      // Here we compare names and not typeinfos since they may come from two different contexts: a compiled
      // and a jitted one.
      if (0 != strcmp(customColumn->GetTypeId().name(), typeid(T).name()))
         throw std::runtime_error(
            std::string("RColumnValue: type specified for column \"" + customColumn->GetName() + "\" is ") +
            TypeID2TypeName(typeid(T)) + " but temporary column has type " +
            TypeID2TypeName(customColumn->GetTypeId()));

      if (customColumn->IsDataSourceColumn()) {
         fColumnKind = EColumnKind::kDataSource;
         fDSValuePtr = static_cast<T **>(customColumn->GetValuePtr(slot));
      } else {
         fColumnKind = EColumnKind::kCustomColumn;
         fCustomValuePtr = static_cast<T *>(customColumn->GetValuePtr(slot));
      }
      fSlot = slot;
   }

   void MakeProxy(TTreeReader *r, const std::string &bn)
   {
      fColumnKind = EColumnKind::kTree;
      fTreeReader = std::make_unique<TreeReader_t>(*r, bn.c_str());
   }

   /// This overload is used to return scalar quantities (i.e. types that are not read into a RVec)
   // This method is executed inside the event-loop, many times per entry
   // If need be, the if statement can be avoided using thunks
   // (have both branches inside functions and have a pointer to the branch to be executed)
   template <typename U = T, typename std::enable_if<!RColumnValue<U>::MustUseRVec_t::value, int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         return *(fTreeReader->Get());
      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload is used to return arrays (i.e. types that are read into a RVec).
   /// In this case the returned T is always a RVec<ColumnValue_t>.
   /// RVec<bool> is treated differently, in a separate overload.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && !std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         // We only use TTreeReaderArrays to read columns that users flagged as type `RVec`, so we need to check
         // that the branch stores the array as contiguous memory that we can actually wrap in an `RVec`.
         // Currently we need the first entry to have been loaded to perform the check
         // TODO Move check to `MakeProxy` once Axel implements this kind of check in TTreeReaderArray using
         // TBranchProxy

         if (EStorageType::kUnknown == fStorageType && readerArray.GetSize() > 1) {
            // We can decide since the array is long enough
            fStorageType =
               (1 == (&readerArray[1] - &readerArray[0])) ? EStorageType::kContiguous : EStorageType::kSparse;
         }

         const auto readerArraySize = readerArray.GetSize();
         if (EStorageType::kContiguous == fStorageType ||
             (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
            if (readerArraySize > 0) {
               // trigger loading of the contents of the TTreeReaderArray
               // the address of the first element in the reader array is not necessarily equal to
               // the address returned by the GetAddress method
               auto readerArrayAddr = &readerArray.At(0);
               T rvec(readerArrayAddr, readerArraySize);
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         } else {
            // The storage is not contiguous or we don't know yet: we cannot but copy into the rvec
#ifndef NDEBUG
            if (!fCopyWarningPrinted) {
               Warning("RColumnValue::Get",
                       "Branch %s hangs from a non-split branch. A copy is being performed in order "
                       "to properly read the content.",
                       readerArray.GetBranchName());
               fCopyWarningPrinted = true;
            }
#else
            (void)fCopyWarningPrinted;
#endif
            if (readerArraySize > 0) {
               T rvec(readerArray.begin(), readerArray.end());
               std::swap(fRVec, rvec);
            } else {
               T emptyVec{};
               std::swap(fRVec, emptyVec);
            }
         }
         return fRVec;

      } else {
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   /// This overload covers the RVec<bool> case. In this case we always copy the contents of TTreeReaderArray<bool>
   /// into RVec<bool> (never take a view into the memory buffer) because the underlying memory buffer might be the
   /// one of a std::vector<bool>, which is not a contiguous slab of bool values.
   /// Note that this also penalizes the case in which the column type is actually bool[], but the possible performance
   /// gains in this edge case is probably not worth the extra complication required to differentiate the two cases.
   template <typename U = T,
             typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && std::is_same<U, RVec<bool>>::value,
                                     int>::type = 0>
   T &Get(Long64_t entry)
   {
      if (fColumnKind == EColumnKind::kTree) {
         auto &readerArray = *fTreeReader;
         const auto readerArraySize = readerArray.GetSize();
         if (readerArraySize > 0) {
            // always perform a copy
            T rvec(readerArray.begin(), readerArray.end());
            std::swap(fRVec, rvec);
         } else {
            T emptyVec{};
            std::swap(fRVec, emptyVec);
         }
         return fRVec;
      } else {
         // business as usual
         fCustomColumn->Update(fSlot, entry);
         return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
      }
   }

   void Reset()
   {
      // This method should by all means not be removed, together with all
      // of its callers, otherwise a race condition takes place in which a
      // TTreeReader and its TTreeReader{Value,Array}s could be deleted
      // concurrently:
      // - Thread #1) a task ends and pushes back processing slot
      // - Thread #2) a task starts and overwrites thread-local TTreeReaderValues
      // - Thread #1) first task deletes TTreeReader
      // See https://github.com/root-project/root/commit/26e8ace6e47de6794ac9ec770c3bbff9b7f2e945
      if (EColumnKind::kTree == fColumnKind) {
         fTreeReader.reset();
      }
   }
};

// Some extern instantiations to speed-up compilation/interpretation time
// These are not active if c++17 is enabled because of a bug in our clang
// See ROOT-9499.
#if __cplusplus < 201703L
extern template class RColumnValue<int>;
extern template class RColumnValue<unsigned int>;
extern template class RColumnValue<char>;
extern template class RColumnValue<unsigned char>;
extern template class RColumnValue<float>;
extern template class RColumnValue<double>;
extern template class RColumnValue<Long64_t>;
extern template class RColumnValue<ULong64_t>;
extern template class RColumnValue<std::vector<int>>;
extern template class RColumnValue<std::vector<unsigned int>>;
extern template class RColumnValue<std::vector<char>>;
extern template class RColumnValue<std::vector<unsigned char>>;
extern template class RColumnValue<std::vector<float>>;
extern template class RColumnValue<std::vector<double>>;
extern template class RColumnValue<std::vector<Long64_t>>;
extern template class RColumnValue<std::vector<ULong64_t>>;
#endif

template <typename T>
struct TRDFValueTuple {
};

template <typename... BranchTypes>
struct TRDFValueTuple<TypeList<BranchTypes...>> {
   using type = std::tuple<RColumnValue<BranchTypes>...>;
};

template <typename BranchType>
using RDFValueTuple_t = typename TRDFValueTuple<BranchType>::type;

/// Clear the proxies of a tuple of RColumnValues
template <typename ValueTuple, std::size_t... S>
void ResetRDFValueTuple(ValueTuple &values, std::index_sequence<S...>)
{
   // hack to expand a parameter pack without c++17 fold expressions.
   std::initializer_list<int> expander{(std::get<S>(values).Reset(), 0)...};
   (void)expander; // avoid "unused variable" warnings
}

} // ns RDF
} // ns Internal
} // ns ROOT

#endif // ROOT_RCOLUMNVALUE
<|endoftext|>


<commit_before>#include "sim_protocol.h"
#include "../HalideRuntime.h"

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

typedef struct _buffer__seq_octet _buffer__seq_octet;
typedef _buffer__seq_octet buffer;
struct _buffer__seq_octet {
   unsigned char* data;
   int dataLen;
};
typedef unsigned int handle_t;

typedef handle_t handle_t;

// This is a basic implementation of the Halide runtime for Hexagon.
void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    // Allocate enough space for aligning the pointer we return.
    const size_t alignment = 128;
    void *orig = malloc(x + alignment);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // We want to store the original pointer prior to the pointer we return.
    void *ptr = (void *)(((size_t)orig + alignment + sizeof(void*) - 1) & ~(alignment - 1));
    ((void **)ptr)[-1] = orig;
    return ptr;
}

void halide_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

typedef int (*set_runtime_t)(halide_malloc_t user_malloc,
                             halide_free_t custom_free,
                             halide_print_t print,
                             halide_error_handler_t error_handler,
                             halide_do_par_for_t do_par_for,
                             halide_do_task_t do_task);

int initialize_kernels(const unsigned char *code, int codeLen,
                       handle_t *module_ptr) {
#if 1  // Use shared object from file
    const char *filename = (const char *)code;
#else
    const char *filename = "/data/halide_kernels.so";
    FILE* fd = fopen(filename, "w");
    if (!fd) {
        halide_print(NULL, "fopen failed\n");
        return -1;
    }

    fwrite(code, codeLen, 1, fd);
    fclose(fd);
#endif
    halide_print(NULL, "dlopen ");
    halide_print(NULL, filename);
    halide_print(NULL, "\n");
    void *lib = dlopen(filename, RTLD_LOCAL | RTLD_LAZY);
    if (!lib) {
        halide_print(NULL, "dlopen failed\n");
        halide_print(NULL, dlerror());
        return -1;
    }
    halide_print(NULL, "dlopen succeeded!\n");

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    set_runtime_t set_runtime = (set_runtime_t)dlsym(lib, "halide_noos_set_runtime");
    if (!set_runtime) {
        dlclose(lib);
        halide_print(NULL, "halide_noos_set_runtime not found in shared object\n");
        return -1;
    }

    int result = set_runtime(halide_malloc,
                             halide_free,
                             halide_print,
                             halide_error,
                             halide_do_par_for,
                             halide_do_task);
    if (result != 0) {
        dlclose(lib);
        halide_print(NULL, "set_runtime failed\n");
        return result;
    }
    *module_ptr = reinterpret_cast<handle_t>(lib);

    return 0;
}

handle_t get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    return reinterpret_cast<handle_t>(dlsym(reinterpret_cast<void*>(module_ptr), name));
}

int run(handle_t module_ptr, handle_t function,
        const buffer *input_buffersPtrs, int input_buffersLen,
        const buffer *input_scalarsPtrs, int input_scalarsLen,
        buffer *output_buffersPtrs, int output_buffersLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = reinterpret_cast<pipeline_argv_t>(function);

    // Construct a list of arguments. This is only part of a
    // buffer_t. We know that the only field of buffer_t that the
    // generated code should access is the host field (any other
    // fields should be passed as their own scalar parameters) so we
    // can just make this dummy buffer_t type.
    struct buffer_t {
        uint64_t dev;
        uint8_t* host;
    };
    void **args = (void **)__builtin_alloca((input_buffersLen + input_scalarsLen + output_buffersLen) * sizeof(void *));
    buffer_t *buffers = (buffer_t *)__builtin_alloca((input_buffersLen + output_buffersLen) * sizeof(buffer_t));

    void **next_arg = &args[0];
    buffer_t *next_buffer_t = &buffers[0];
    // Input buffers come first.
    for (int i = 0; i < input_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = input_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Input scalars are next.
    for (int i = 0; i < input_scalarsLen; i++, next_arg++) {
        *next_arg = input_scalarsPtrs[i].data;
    }
    // Output buffers are last.
    for (int i = 0; i < output_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = output_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int release_kernels(handle_t module_ptr, int codeLen) {
    dlclose(reinterpret_cast<void*>(module_ptr));
    return 0;
}

extern "C" {

void halide_print(void *user_context, const char *str) {
    printf("%s", str);
}

// The global symbols with which we pass RPC commands and results.
volatile int rpc_call = Message::Break;

#if 0
volatile int rpc_args[16];
#define RPC_ARG(i) rpc_args[i]
#else
volatile int rpc_arg0;
volatile int rpc_arg1;
volatile int rpc_arg2;
volatile int rpc_arg3;
volatile int rpc_arg4;
volatile int rpc_arg5;
volatile int rpc_arg6;
volatile int rpc_arg7;
#define RPC_ARG(i) rpc_arg##i
#endif

volatile int rpc_ret = 0;

}

int main(int argc, const char **argv) {
    printf("Simulator loop running...\n");
    while(true) {
        fflush(stdout);
        switch (rpc_call) {
        case Message::None:
            break;
        case Message::Alloc:
            printf("Alloc(%d)\n", RPC_ARG(0));
            rpc_ret = reinterpret_cast<int>(halide_malloc(NULL, RPC_ARG(0)));
            break;
        case Message::Free:
            printf("Free\n");
            halide_free(NULL, reinterpret_cast<void*>(RPC_ARG(0)));
            rpc_ret = 0;
            break;
        case Message::InitKernels:
            printf("InitKernels\n");
            rpc_ret = initialize_kernels(
                reinterpret_cast<unsigned char*>(RPC_ARG(0)),
                RPC_ARG(1),
                reinterpret_cast<handle_t*>(RPC_ARG(2)));
            break;
        case Message::Run:
            printf("Run\n");
            rpc_ret = run(
                static_cast<handle_t>(RPC_ARG(0)),
                static_cast<handle_t>(RPC_ARG(1)),
                reinterpret_cast<const buffer*>(RPC_ARG(2)),
                RPC_ARG(3),
                reinterpret_cast<const buffer*>(RPC_ARG(4)),
                RPC_ARG(5),
                reinterpret_cast<buffer*>(RPC_ARG(6)),
                RPC_ARG(7));
            break;
        case Message::ReleaseKernels:
            printf("ReleaseKernels\n");
            rpc_ret = release_kernels(
                static_cast<handle_t>(RPC_ARG(0)),
                RPC_ARG(1));
            break;
        case Message::Break:
            printf("Break\n");
            return 0;
        default:
            printf("Unknown message!\n");
            return -1;
        }
        // Setting the message to zero indicates to the caller that
        // we're done processing the message.
        rpc_call = Message::None;
    }
    printf("Unreachable!\n");
    return 0;
}
<commit_msg>Fixed dlopen/dlsym on the simulator.<commit_after>#include "sim_protocol.h"
#include "../HalideRuntime.h"

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

typedef struct _buffer__seq_octet _buffer__seq_octet;
typedef _buffer__seq_octet buffer;
struct _buffer__seq_octet {
   unsigned char* data;
   int dataLen;
};
typedef unsigned int handle_t;

typedef handle_t handle_t;

// This is a basic implementation of the Halide runtime for Hexagon.
void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    // Allocate enough space for aligning the pointer we return.
    const size_t alignment = 128;
    void *orig = malloc(x + alignment);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // We want to store the original pointer prior to the pointer we return.
    void *ptr = (void *)(((size_t)orig + alignment + sizeof(void*) - 1) & ~(alignment - 1));
    ((void **)ptr)[-1] = orig;
    return ptr;
}

void halide_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

void init() {
    // The simulator needs this call to enable dlopen to work...
    const char *builtin[] = {"libgcc.so", "libc.so", "libstdc++.so"};
    dlinit(3, const_cast<char**>(builtin));
}

typedef int (*set_runtime_t)(halide_malloc_t user_malloc,
                             halide_free_t custom_free,
                             halide_print_t print,
                             halide_error_handler_t error_handler,
                             halide_do_par_for_t do_par_for,
                             halide_do_task_t do_task);

int initialize_kernels(const unsigned char *code, int codeLen,
                       handle_t *module_ptr) {
    init();

#if 1  // Use shared object from file
    const char *filename = (const char *)code;
#else
    const char *filename = "/data/halide_kernels.so";
    FILE* fd = fopen(filename, "w");
    if (!fd) {
        halide_print(NULL, "fopen failed\n");
        return -1;
    }

    fwrite(code, codeLen, 1, fd);
    fclose(fd);
#endif
    void *lib = dlopen(filename, RTLD_LOCAL | RTLD_LAZY);
    if (!lib) {
        halide_print(NULL, "dlopen failed\n");
        halide_print(NULL, dlerror());
        return -1;
    }

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    set_runtime_t set_runtime = (set_runtime_t)dlsym(lib, "halide_noos_set_runtime");
    if (!set_runtime) {
        dlclose(lib);
        halide_print(NULL, "halide_noos_set_runtime not found in shared object\n");
        return -1;
    }

    int result = set_runtime(halide_malloc,
                             halide_free,
                             halide_print,
                             halide_error,
                             halide_do_par_for,
                             halide_do_task);
    if (result != 0) {
        dlclose(lib);
        halide_print(NULL, "set_runtime failed\n");
        return result;
    }
    *module_ptr = reinterpret_cast<handle_t>(lib);

    return 0;
}

handle_t get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    return reinterpret_cast<handle_t>(dlsym(reinterpret_cast<void*>(module_ptr), name));
}

int run(handle_t module_ptr, handle_t function,
        const buffer *input_buffersPtrs, int input_buffersLen,
        const buffer *input_scalarsPtrs, int input_scalarsLen,
        buffer *output_buffersPtrs, int output_buffersLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = reinterpret_cast<pipeline_argv_t>(function);

    // Construct a list of arguments. This is only part of a
    // buffer_t. We know that the only field of buffer_t that the
    // generated code should access is the host field (any other
    // fields should be passed as their own scalar parameters) so we
    // can just make this dummy buffer_t type.
    struct buffer_t {
        uint64_t dev;
        uint8_t* host;
    };
    void **args = (void **)__builtin_alloca((input_buffersLen + input_scalarsLen + output_buffersLen) * sizeof(void *));
    buffer_t *buffers = (buffer_t *)__builtin_alloca((input_buffersLen + output_buffersLen) * sizeof(buffer_t));

    void **next_arg = &args[0];
    buffer_t *next_buffer_t = &buffers[0];
    // Input buffers come first.
    for (int i = 0; i < input_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = input_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Input scalars are next.
    for (int i = 0; i < input_scalarsLen; i++, next_arg++) {
        *next_arg = input_scalarsPtrs[i].data;
    }
    // Output buffers are last.
    for (int i = 0; i < output_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = output_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int release_kernels(handle_t module_ptr, int codeLen) {
    dlclose(reinterpret_cast<void*>(module_ptr));
    return 0;
}

extern "C" {

void halide_print(void *user_context, const char *str) {
    printf("%s", str);
}

// The global symbols with which we pass RPC commands and results.
volatile int rpc_call = Message::Break;

#if 0
volatile int rpc_args[16];
#define RPC_ARG(i) rpc_args[i]
#else
volatile int rpc_arg0;
volatile int rpc_arg1;
volatile int rpc_arg2;
volatile int rpc_arg3;
volatile int rpc_arg4;
volatile int rpc_arg5;
volatile int rpc_arg6;
volatile int rpc_arg7;
#define RPC_ARG(i) rpc_arg##i
#endif

volatile int rpc_ret = 0;

}

int main(int argc, const char **argv) {
    printf("Simulator loop running...\n");
    while(true) {
        fflush(stdout);
        switch (rpc_call) {
        case Message::None:
            break;
        case Message::Alloc:
            printf("Alloc(%d)\n", RPC_ARG(0));
            rpc_ret = reinterpret_cast<int>(halide_malloc(NULL, RPC_ARG(0)));
            break;
        case Message::Free:
            printf("Free\n");
            halide_free(NULL, reinterpret_cast<void*>(RPC_ARG(0)));
            rpc_ret = 0;
            break;
        case Message::InitKernels:
            printf("InitKernels\n");
            rpc_ret = initialize_kernels(
                reinterpret_cast<unsigned char*>(RPC_ARG(0)),
                RPC_ARG(1),
                reinterpret_cast<handle_t*>(RPC_ARG(2)));
            break;
        case Message::Run:
            printf("Run\n");
            rpc_ret = run(
                static_cast<handle_t>(RPC_ARG(0)),
                static_cast<handle_t>(RPC_ARG(1)),
                reinterpret_cast<const buffer*>(RPC_ARG(2)),
                RPC_ARG(3),
                reinterpret_cast<const buffer*>(RPC_ARG(4)),
                RPC_ARG(5),
                reinterpret_cast<buffer*>(RPC_ARG(6)),
                RPC_ARG(7));
            break;
        case Message::ReleaseKernels:
            printf("ReleaseKernels\n");
            rpc_ret = release_kernels(
                static_cast<handle_t>(RPC_ARG(0)),
                RPC_ARG(1));
            break;
        case Message::Break:
            printf("Break\n");
            return 0;
        default:
            printf("Unknown message!\n");
            return -1;
        }
        // Setting the message to zero indicates to the caller that
        // we're done processing the message.
        rpc_call = Message::None;
    }
    printf("Unreachable!\n");
    return 0;
}
<|endoftext|>


<commit_before>#include "sim_protocol.h"
#include "../HalideRuntime.h"

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

#include <string.h>

#include "hexagon_standalone.h"

typedef struct _buffer__seq_octet _buffer__seq_octet;
typedef _buffer__seq_octet buffer;
struct _buffer__seq_octet {
   unsigned char* data;
   int dataLen;
};
typedef unsigned int handle_t;

typedef handle_t handle_t;

const int hvx_alignment = 128;

// Provide an implementation of qurt to redirect to the appropriate
// simulator calls.
extern "C" {

int qurt_hvx_lock(int mode) {
    SIM_ACQUIRE_HVX;
    if (mode == 0) {
        SIM_CLEAR_HVX_DOUBLE_MODE;
    } else {
        SIM_SET_HVX_DOUBLE_MODE;
    }
    return 0;
}

int qurt_hvx_unlock() {
    SIM_RELEASE_HVX;
    return 0;
}

}  // extern "C"

void halide_print(void *user_context, const char *str) {
    fprintf(stderr, "%s", str);
}

// This is a basic implementation of the Halide runtime for Hexagon.
void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    return memalign(hvx_alignment, x);
}

void halide_free(void *user_context, void *ptr) {
    free(ptr);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

void *halide_get_symbol(const char *name) {
    return dlsym(RTLD_DEFAULT, name);
}

void *halide_load_library(const char *name) {
    return dlopen(name, RTLD_LAZY);
}

void *halide_get_library_symbol(void *lib, const char *name) {
    return dlsym(lib, name);
}

typedef int (*set_runtime_t)(halide_malloc_t user_malloc,
                             halide_free_t custom_free,
                             halide_print_t print,
                             halide_error_handler_t error_handler,
                             halide_do_par_for_t do_par_for,
                             halide_do_task_t do_task,
                             void *(*)(const char *),
                             void *(*)(const char *),
                             void *(*)(void *, const char *));

int initialize_kernels(const unsigned char *code, int codeLen,
                       handle_t *module_ptr) {
#if 1  // Use shared object from file
    const char *filename = (const char *)code;
#else
    const char *filename = "/data/halide_kernels.so";
    FILE* fd = fopen(filename, "w");
    if (!fd) {
        halide_print(NULL, "fopen failed\n");
        return -1;
    }

    fwrite(code, codeLen, 1, fd);
    fclose(fd);
#endif
    void *lib = dlopen(filename, RTLD_LOCAL | RTLD_LAZY);
    if (!lib) {
        halide_print(NULL, "dlopen failed\n");
        halide_print(NULL, dlerror());
        return -1;
    }

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    set_runtime_t set_runtime = (set_runtime_t)dlsym(lib, "halide_noos_set_runtime");
    if (!set_runtime) {
        dlclose(lib);
        halide_print(NULL, "halide_noos_set_runtime not found in shared object\n");
        return -1;
    }

    int result = set_runtime(halide_malloc,
                             halide_free,
                             halide_print,
                             halide_error,
                             halide_do_par_for,
                             halide_do_task,
                             halide_get_symbol,
                             halide_load_library,
                             halide_get_library_symbol);
    if (result != 0) {
        dlclose(lib);
        halide_print(NULL, "set_runtime failed\n");
        return result;
    }
    *module_ptr = reinterpret_cast<handle_t>(lib);

    return 0;
}

handle_t get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    return reinterpret_cast<handle_t>(dlsym(reinterpret_cast<void*>(module_ptr), name));
}

int run(handle_t module_ptr, handle_t function,
        const buffer *input_buffersPtrs, int input_buffersLen,
        buffer *output_buffersPtrs, int output_buffersLen,
        const buffer *input_scalarsPtrs, int input_scalarsLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = reinterpret_cast<pipeline_argv_t>(function);

    // Construct a list of arguments. This is only part of a
    // buffer_t. We know that the only field of buffer_t that the
    // generated code should access is the host field (any other
    // fields should be passed as their own scalar parameters) so we
    // can just make this dummy buffer_t type.
    struct buffer_t {
        uint64_t dev;
        uint8_t* host;
    };
    void **args = (void **)__builtin_alloca((input_buffersLen + input_scalarsLen + output_buffersLen) * sizeof(void *));
    buffer_t *buffers = (buffer_t *)__builtin_alloca((input_buffersLen + output_buffersLen) * sizeof(buffer_t));

    void **next_arg = &args[0];
    buffer_t *next_buffer_t = &buffers[0];
    // Input buffers come first.
    for (int i = 0; i < input_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = input_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Output buffers are next.
    for (int i = 0; i < output_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = output_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Input scalars are last.
    for (int i = 0; i < input_scalarsLen; i++, next_arg++) {
        *next_arg = input_scalarsPtrs[i].data;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int release_kernels(handle_t module_ptr, int codeLen) {
    dlclose(reinterpret_cast<void*>(module_ptr));
    return 0;
}

extern "C" {

// The global symbols with which we pass RPC commands and results.
volatile int rpc_call = Message::None;

#if 0
volatile int rpc_args[16];
#define RPC_ARG(i) rpc_args[i]
#else
volatile int rpc_arg0;
volatile int rpc_arg1;
volatile int rpc_arg2;
volatile int rpc_arg3;
volatile int rpc_arg4;
volatile int rpc_arg5;
volatile int rpc_arg6;
volatile int rpc_arg7;
#define RPC_ARG(i) rpc_arg##i
#endif

volatile int rpc_ret = 0;

void set_rpc_return(int value) {
    rpc_ret = value;
    rpc_call = Message::None;
}

}

int main(int argc, const char **argv) {
    // The simulator needs this call to enable dlopen to work...
    char libgcc[] = "libgcc.so";
    char libc[] = "libc.so";
    char libstdcpp[] = "libstdc++.so";
    char *builtin[] = {libgcc, libc, libstdcpp};
    dlinit(3, builtin);

    while(true) {
        switch (rpc_call) {
        case Message::None:
            break;
        case Message::Alloc:
            set_rpc_return(reinterpret_cast<int>(memalign(hvx_alignment, RPC_ARG(0))));
            break;
        case Message::Free:
            free(reinterpret_cast<void*>(RPC_ARG(0)));
            set_rpc_return(0);
            break;
        case Message::InitKernels:
            set_rpc_return(initialize_kernels(
                reinterpret_cast<unsigned char*>(RPC_ARG(0)),
                RPC_ARG(1),
                reinterpret_cast<handle_t*>(RPC_ARG(2))));
            break;
        case Message::GetSymbol:
            set_rpc_return(get_symbol(
                static_cast<handle_t>(RPC_ARG(0)),
                reinterpret_cast<const char *>(RPC_ARG(1)),
                RPC_ARG(2)));
            break;
        case Message::Run:
            set_rpc_return(run(
                static_cast<handle_t>(RPC_ARG(0)),
                static_cast<handle_t>(RPC_ARG(1)),
                reinterpret_cast<const buffer*>(RPC_ARG(2)),
                RPC_ARG(3),
                reinterpret_cast<buffer*>(RPC_ARG(4)),
                RPC_ARG(5),
                reinterpret_cast<const buffer*>(RPC_ARG(6)),
                RPC_ARG(7)));
            break;
        case Message::ReleaseKernels:
            set_rpc_return(release_kernels(
                static_cast<handle_t>(RPC_ARG(0)),
                RPC_ARG(1)));
            break;
        case Message::Break:
            return 0;
        default:
            fprintf(stderr, "Unknown message: %d\n", rpc_call);
            return -1;
        }
    }
    fprintf(stderr, "Unreachable!\n");
    return 0;
}
<commit_msg>Remove unnecessary include.<commit_after>#include "sim_protocol.h"
#include "../HalideRuntime.h"

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

#include "hexagon_standalone.h"

typedef struct _buffer__seq_octet _buffer__seq_octet;
typedef _buffer__seq_octet buffer;
struct _buffer__seq_octet {
   unsigned char* data;
   int dataLen;
};
typedef unsigned int handle_t;

typedef handle_t handle_t;

const int hvx_alignment = 128;

// Provide an implementation of qurt to redirect to the appropriate
// simulator calls.
extern "C" {

int qurt_hvx_lock(int mode) {
    SIM_ACQUIRE_HVX;
    if (mode == 0) {
        SIM_CLEAR_HVX_DOUBLE_MODE;
    } else {
        SIM_SET_HVX_DOUBLE_MODE;
    }
    return 0;
}

int qurt_hvx_unlock() {
    SIM_RELEASE_HVX;
    return 0;
}

}  // extern "C"

void halide_print(void *user_context, const char *str) {
    fprintf(stderr, "%s", str);
}

// This is a basic implementation of the Halide runtime for Hexagon.
void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    return memalign(hvx_alignment, x);
}

void halide_free(void *user_context, void *ptr) {
    free(ptr);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

void *halide_get_symbol(const char *name) {
    return dlsym(RTLD_DEFAULT, name);
}

void *halide_load_library(const char *name) {
    return dlopen(name, RTLD_LAZY);
}

void *halide_get_library_symbol(void *lib, const char *name) {
    return dlsym(lib, name);
}

typedef int (*set_runtime_t)(halide_malloc_t user_malloc,
                             halide_free_t custom_free,
                             halide_print_t print,
                             halide_error_handler_t error_handler,
                             halide_do_par_for_t do_par_for,
                             halide_do_task_t do_task,
                             void *(*)(const char *),
                             void *(*)(const char *),
                             void *(*)(void *, const char *));

int initialize_kernels(const unsigned char *code, int codeLen,
                       handle_t *module_ptr) {
#if 1  // Use shared object from file
    const char *filename = (const char *)code;
#else
    const char *filename = "/data/halide_kernels.so";
    FILE* fd = fopen(filename, "w");
    if (!fd) {
        halide_print(NULL, "fopen failed\n");
        return -1;
    }

    fwrite(code, codeLen, 1, fd);
    fclose(fd);
#endif
    void *lib = dlopen(filename, RTLD_LOCAL | RTLD_LAZY);
    if (!lib) {
        halide_print(NULL, "dlopen failed\n");
        halide_print(NULL, dlerror());
        return -1;
    }

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    set_runtime_t set_runtime = (set_runtime_t)dlsym(lib, "halide_noos_set_runtime");
    if (!set_runtime) {
        dlclose(lib);
        halide_print(NULL, "halide_noos_set_runtime not found in shared object\n");
        return -1;
    }

    int result = set_runtime(halide_malloc,
                             halide_free,
                             halide_print,
                             halide_error,
                             halide_do_par_for,
                             halide_do_task,
                             halide_get_symbol,
                             halide_load_library,
                             halide_get_library_symbol);
    if (result != 0) {
        dlclose(lib);
        halide_print(NULL, "set_runtime failed\n");
        return result;
    }
    *module_ptr = reinterpret_cast<handle_t>(lib);

    return 0;
}

handle_t get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    return reinterpret_cast<handle_t>(dlsym(reinterpret_cast<void*>(module_ptr), name));
}

int run(handle_t module_ptr, handle_t function,
        const buffer *input_buffersPtrs, int input_buffersLen,
        buffer *output_buffersPtrs, int output_buffersLen,
        const buffer *input_scalarsPtrs, int input_scalarsLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = reinterpret_cast<pipeline_argv_t>(function);

    // Construct a list of arguments. This is only part of a
    // buffer_t. We know that the only field of buffer_t that the
    // generated code should access is the host field (any other
    // fields should be passed as their own scalar parameters) so we
    // can just make this dummy buffer_t type.
    struct buffer_t {
        uint64_t dev;
        uint8_t* host;
    };
    void **args = (void **)__builtin_alloca((input_buffersLen + input_scalarsLen + output_buffersLen) * sizeof(void *));
    buffer_t *buffers = (buffer_t *)__builtin_alloca((input_buffersLen + output_buffersLen) * sizeof(buffer_t));

    void **next_arg = &args[0];
    buffer_t *next_buffer_t = &buffers[0];
    // Input buffers come first.
    for (int i = 0; i < input_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = input_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Output buffers are next.
    for (int i = 0; i < output_buffersLen; i++, next_arg++, next_buffer_t++) {
        next_buffer_t->host = output_buffersPtrs[i].data;
        *next_arg = next_buffer_t;
    }
    // Input scalars are last.
    for (int i = 0; i < input_scalarsLen; i++, next_arg++) {
        *next_arg = input_scalarsPtrs[i].data;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int release_kernels(handle_t module_ptr, int codeLen) {
    dlclose(reinterpret_cast<void*>(module_ptr));
    return 0;
}

extern "C" {

// The global symbols with which we pass RPC commands and results.
volatile int rpc_call = Message::None;

#if 0
volatile int rpc_args[16];
#define RPC_ARG(i) rpc_args[i]
#else
volatile int rpc_arg0;
volatile int rpc_arg1;
volatile int rpc_arg2;
volatile int rpc_arg3;
volatile int rpc_arg4;
volatile int rpc_arg5;
volatile int rpc_arg6;
volatile int rpc_arg7;
#define RPC_ARG(i) rpc_arg##i
#endif

volatile int rpc_ret = 0;

void set_rpc_return(int value) {
    rpc_ret = value;
    rpc_call = Message::None;
}

}

int main(int argc, const char **argv) {
    // The simulator needs this call to enable dlopen to work...
    char libgcc[] = "libgcc.so";
    char libc[] = "libc.so";
    char libstdcpp[] = "libstdc++.so";
    char *builtin[] = {libgcc, libc, libstdcpp};
    dlinit(3, builtin);

    while(true) {
        switch (rpc_call) {
        case Message::None:
            break;
        case Message::Alloc:
            set_rpc_return(reinterpret_cast<int>(memalign(hvx_alignment, RPC_ARG(0))));
            break;
        case Message::Free:
            free(reinterpret_cast<void*>(RPC_ARG(0)));
            set_rpc_return(0);
            break;
        case Message::InitKernels:
            set_rpc_return(initialize_kernels(
                reinterpret_cast<unsigned char*>(RPC_ARG(0)),
                RPC_ARG(1),
                reinterpret_cast<handle_t*>(RPC_ARG(2))));
            break;
        case Message::GetSymbol:
            set_rpc_return(get_symbol(
                static_cast<handle_t>(RPC_ARG(0)),
                reinterpret_cast<const char *>(RPC_ARG(1)),
                RPC_ARG(2)));
            break;
        case Message::Run:
            set_rpc_return(run(
                static_cast<handle_t>(RPC_ARG(0)),
                static_cast<handle_t>(RPC_ARG(1)),
                reinterpret_cast<const buffer*>(RPC_ARG(2)),
                RPC_ARG(3),
                reinterpret_cast<buffer*>(RPC_ARG(4)),
                RPC_ARG(5),
                reinterpret_cast<const buffer*>(RPC_ARG(6)),
                RPC_ARG(7)));
            break;
        case Message::ReleaseKernels:
            set_rpc_return(release_kernels(
                static_cast<handle_t>(RPC_ARG(0)),
                RPC_ARG(1)));
            break;
        case Message::Break:
            return 0;
        default:
            fprintf(stderr, "Unknown message: %d\n", rpc_call);
            return -1;
        }
    }
    fprintf(stderr, "Unreachable!\n");
    return 0;
}
<|endoftext|>