<commit_before>/*
 * Copyright (C) 2017 Rene Herthel
 * Copyright (C) 2017 Jonas Fuhrmann
 *
 * This file is subject to the terms and conditions of the MIT License.
 * See the file LICENSE in the top level directory for more details.
 */

/**
 * @ingroup    height_measurement
 * @{
 *
 * @brief      Service function declaration of the HeightMeasurement component
 *
 * @author     Rene Herthel <rene.herthel@haw-hamburg.de>
 * @author     Jonas Fuhrmann <jonas.fuhrmann@haw-hamburg.de>
 */

#include "HeightMeasurementService.h"
#include "HeightMeasurementHal.h"

HeightMeasurementService::HeightMeasurementService(int receive_chid, int send_chid, CalibrationData *calibrationDataPtr)
    :    stateMachine(send_chid)
    ,    calibrationDataPtr(calibrationDataPtr)
{
    // Creates the thread for the measurement with the receive channel to send on it.
    measurementThread = std::thread(&HeightMeasurementService::measuringTask, this, receive_chid);
    // Creates the thread for the statemachine with the receive channel to listen on it.
    stateMachineThread = std::thread(&HeightMeasurementService::stateMachineTask, this, receive_chid);
}

HeightMeasurementService::~HeightMeasurementService() {
    // Nothing todo so far.
}

void HeightMeasurementService::measuringTask(int receive_chid) {
    int16_t data = 0;                                    /*< The current measured data. */
    HeightContext::Signal state = HeightContext::START;  /*< The current state of the statemachine. */
    int16_t maxHeight = 0;                               /*< The maximum valid height. */
    int16_t minHeight = 0;                               /*< The minimum valid height. */
    HeightMeasurementHal hal;                            /*< The hal object to access the HW. */

    // Connect to the receive channel for sending pulse-messages on it.
    int coid = ConnectAttach_r(ND_LOCAL_NODE, 0, receive_chid, 0, 0);

    // Do error handling, if there is no channel available.
    if (coid < 0) {
      // TODO: Error handling.
    }

    /* TODO: Make this thread terminating from outside.
     *       -> volatile bool isRunning.
     * TODO: Make this more fancy.
     *
     * Check if the current measured data is in a valid range of the
     * corresponding calibrated data. If it is so, send a signal to the receive-
     * channel, where the statemachine is listening and could do the next
     * transition.
     */
    while (1) {
        hal.read(data);

        maxHeight = data + DELTA_VAL;
        minHeight = data - DELTA_VAL;

        if (state != HeightContext::REF_HEIGHT) {
            if (maxHeight < REF_HEIGHT_VAL && minHeight > REF_HEIGHT_VAL) {
                // TODO
            }
        }
        else if (state != HeightContext::HOLE_HEIGHT) {
            if (maxHeight < HOLE_HEIGHT_VAL && minHeight > HOLE_HEIGHT_VAL) {
                // TODO
            }
        }
        else if (state != HeightContext::SURFACE_HEIGHT) {
            if (maxHeight < SURFACE_HEIGHT_VAL && minHeight > SURFACE_HEIGHT_VAL) {
                // TODO
            }
        }
        else if (state != HeightContext::LOW_HEIGHT) {
            if (maxHeight < LOW_HEIGHT_VAL && minHeight > LOW_HEIGHT_VAL) {
                // TODO
            }
        }
        else if (state != HeightContext::HIGH_HEIGHT) {
            if (maxHeight < HIGH_HEIGHT_VAL && minHeight > HIGH_HEIGHT_VAL) {
                // TODO
            }
        }
    }
}

void HeightMeasurementService::stateMachineTask(int receive_chid) {
    // Connect the statemachine to the receive channel to listen on it.
    int coid = ConnectAttach_r(ND_LOCAL_NODE, 0, receive_chid, 0, 0);

    // Do error handling if there is no channel to connect.
    if (coid < 0) {
        // TODO: Error handling.
    }

    // Structure that describes a pulse.
    struct _pulse pulse;

    /* TODO: Make this thread terminating from outside.
     *       -> volatile bool isRunning.
     *
     * Wait for a new incoming pulse-message to do the next transition.
     */
    while (1) {

        // Returns 0 on success and a negative value on error.
        int err = MsgReceivePulse_r(receive_chid, &pulse, sizeof(_pulse), NULL);

        // Do error handling, if there occurs an error.
        if (err < 0) {
            // TODO: Error handling.
            // EFAULT, EINTR, ESRCH, ETIMEDOUT -> see qnx-manual.
        }

        // Signalize the statemachine for the next transition.
        stateMachine.process((HeightContext::Signal) pulse.value.sival_int);
    }
}

/** @} */
<commit_msg>Enhanced the service class.<commit_after>/*
 * Copyright (C) 2017 Rene Herthel
 * Copyright (C) 2017 Jonas Fuhrmann
 *
 * This file is subject to the terms and conditions of the MIT License.
 * See the file LICENSE in the top level directory for more details.
 */

/**
 * @ingroup    height_measurement
 * @{
 *
 * @brief      Service function declaration of the HeightMeasurement component
 *
 * @author     Rene Herthel <rene.herthel@haw-hamburg.de>
 * @author     Jonas Fuhrmann <jonas.fuhrmann@haw-hamburg.de>
 */

#include "HeightMeasurementService.h"
#include "HeightMeasurementHal.h"

/*
 * @brief Macros to check if the measured data is in range of the corresponding state.
 *
 * @param [DATA] The measured data.
 * @param [CAL]  The reference value of the calibrated data.
 * @{
 */
#define DATA_IS_IN_RANGE(DATA, CAL)    (((DATA - DELTA_VAL) < CAL) && ((DATA + DELTA_VAL) > CAL))
/** @} */

HeightMeasurementService::HeightMeasurementService(int receive_chid, int send_chid, CalibrationData *calibrationDataPtr)
    :    stateMachine(send_chid)
    ,    calibrationDataPtr(calibrationDataPtr)
{
    // Creates the thread for the measurement with the receive channel to send on it.
    measurementThread = std::thread(&HeightMeasurementService::measuringTask, this, receive_chid);
    // Creates the thread for the statemachine with the receive channel to listen on it.
    stateMachineThread = std::thread(&HeightMeasurementService::stateMachineTask, this, receive_chid);
}

HeightMeasurementService::~HeightMeasurementService() {
    // TODO Kill the threads.
}

void HeightMeasurementService::measuringTask(int receive_chid) {
    int16_t data = 0;                                    /*< The current measured data.*/
    HeightContext::Signal state = HeightContext::START;  /*< The current state of the statemachine.*/
    Heightcontext::Signal oldState = state;              /*< The old state of the statemachine.*/
    HeightMeasurementHal hal;                            /*< The hal object to access the HW.*/
    int err = 0;                                         /*< Return value of msgSend.*/
    struct _pulse pulse;                                 /*< Structure that describes a pulse.*/

    // Connect to the receive channel for sending pulse-messages on it.
    int coid = ConnectAttach_r(ND_LOCAL_NODE, 0, receive_chid, 0, 0);

    // Do error handling, if there is no channel available.
    if (coid < 0) {
        // TODO: Error handling.
        std::cout<<"[measuringTask] Coid error."<<std::endl;
    }

    /* TODO: Make this thread terminating from outside.
     *       -> volatile bool isRunning.
     *
     * Check if the current measured data is in a valid range of the
     * corresponding calibrated data. If it is so, send a signal to the receive-
     * channel, where the statemachine is listening and will do the next
     * transition.
     */
    while (1) {
        hal.read(data);

        if (DATA_IS_IN_RANGE(data, REF_HEIGHT_VAL)) {
            state = HeightContext::REF_HEIGHT;
        }
        else if (DATA_IS_IN_RANGE(data, HOLE_HEIGHT_VAL)) {
            state = HeightContext::HOLE_HEIGHT;
        }
        else if (DATA_IS_IN_RANGE(data, SURFACE_HEIGHT_VAL)) {
            state = HeightContext::SURFACE_HEIGHT;
        }
        else if (DATA_IS_IN_RANGE(data, LOW_HEIGHT_VAL)) {
            state = HeightContext::LOW_HEIGHT;
        }
        else if (DATA_IS_IN_RANGE(data, HIGH_HEIGHT_VAL)) {
            state = HeightContext::HIGH_HEIGHT;
        }

        // Only send a message, when there was a new state.
        if (state != oldState) {
            err = MsgSendPulse_r(coid, sched_get_priority_min(0), 0, (sigval)state);

            if (err < 0) {
                // TODO Error handling.
                std::cout<<"[measuringTask] Error on sending pulse message."<<std::endl;
            }
        }

        // Remember the current state as old state for the next loop.
        oldState = state;
    }
}

void HeightMeasurementService::stateMachineTask(int receive_chid) {
    // Connect the statemachine to the receive channel to listen on it.
    int coid = ConnectAttach_r(ND_LOCAL_NODE, 0, receive_chid, 0, 0);

    // Do error handling if there is no channel to connect.
    if (coid < 0) {
        // TODO: Error handling.
        std::cout<<"[stateMachineTask] Coid error."
    }

    // Structure that describes a pulse.
    struct _pulse pulse;

    /* TODO: Make this thread terminating from outside.
     *       -> volatile bool isRunning.
     *
     * Wait for a new incoming pulse-message to do the next transition.
     */
    while (1) {

        // Returns 0 on success and a negative value on error.
        int err = MsgReceivePulse_r(receive_chid, &pulse, sizeof(_pulse), NULL);

        // Do error handling, if there occurs an error.
        if (err < 0) {
            // TODO: Error handling.
            // EFAULT, EINTR, ESRCH, ETIMEDOUT -> see qnx-manual.
            std::cout<<"[stateMachineTask] Error on receiving pulse message."<<std::endl;
        }

        // Signalize the statemachine for the next transition.
        stateMachine.process((HeightContext::Signal) pulse.value.sival_int);
    }
}

/** @} */
<|endoftext|>


<commit_before>#include <FancyMeshComponent.hpp>

#include <iostream>

#include <Core/String/StringUtils.hpp>
#include <Core/Mesh/MeshUtils.hpp>

#include <Core/Geometry/Normal/Normal.hpp>

#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Managers/ComponentMessenger/ComponentMessenger.hpp>

#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectTypes.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfiguration.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderProgramManager.hpp>
#include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>

#include <Engine/Assets/FileData.hpp>
#include <Engine/Assets/GeometryData.hpp>

using Ra::Engine::ComponentMessenger;

namespace FancyMeshPlugin
{
    FancyMeshComponent::FancyMeshComponent(const std::string& name , bool deformable)
        : Ra::Engine::Component( name  ) , m_deformable(deformable)
    {
    }

    FancyMeshComponent::~FancyMeshComponent()
    {
    }

    void FancyMeshComponent::initialize()
    {
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh, const std::string& name )
    {
        Ra::Engine::RenderTechnique* technique = new Ra::Engine::RenderTechnique;
        technique->material = new Ra::Engine::Material( "Default" );
        technique->shaderConfig = Ra::Engine::ShaderConfiguration( "Default", "../Shaders" );

        addMeshRenderObject(mesh, name, technique);
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh,
                                                  const std::string& name,
                                                  Ra::Engine::RenderTechnique* technique )
    {
        setupIO(name);

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( name, this, Ra::Engine::RenderObjectType::Fancy );
        renderObject->setVisible( true );
        renderObject->setRenderTechnique( technique );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( name ) );
        displayMesh->loadGeometry( mesh );
        renderObject->setMesh( displayMesh );
        addRenderObject( renderObject );
    }

    void FancyMeshComponent::handleMeshLoading( const Ra::Asset::GeometryData* data )
    {
        std::string name( m_name );
        name.append( "_" + data->getName() );

        std::string roName = name;
        roName.append( "_RO" );

        std::string meshName = name;
        meshName.append( "_Mesh" );

        std::string matName = name;
        matName.append( "_Mat" );

        m_contentName = data->getName();

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::Fancy );
        renderObject->setVisible( true );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( meshName ) );

        Ra::Core::TriangleMesh mesh;
        for (size_t i = 0; i < data->getVerticesSize(); ++i)
        {
            mesh.m_vertices.push_back(data->getFrame() * data->getVertices()[i]);
            mesh.m_normals.push_back(data->getNormals()[i]);
        }

        for (const auto& face : data->getFaces())
        {
            mesh.m_triangles.push_back(face.head<3>());
        }

        setupIO( data->getName());

        displayMesh->loadGeometry(mesh);

        Ra::Core::Vector3Array tangents;
        Ra::Core::Vector3Array bitangents;
        Ra::Core::Vector3Array texcoords;

        Ra::Core::Vector4Array colors;

        for ( const auto& v : data->getTangents() )     tangents.push_back( v );
        for ( const auto& v : data->getBiTangents() )   bitangents.push_back( v );
        for ( const auto& v : data->getTexCoords() )    texcoords.push_back( v );
        for ( const auto& v : data->getColors() )       colors.push_back( v );

        displayMesh->addData( Ra::Engine::Mesh::VERTEX_TANGENT, tangents );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_BITANGENT, bitangents );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_TEXCOORD, texcoords );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
        // FIXME(Charly): Should not weights be part of the geometry ?
        //        mesh->addData( Ra::Engine::Mesh::VERTEX_WEIGHTS, meshData.weights );

        renderObject->setMesh( displayMesh );

        m_meshIndex = addRenderObject(renderObject);

        Ra::Engine::RenderTechnique* rt = new Ra::Engine::RenderTechnique;
        Ra::Engine::Material* mat = new Ra::Engine::Material( matName );
        auto m = data->getMaterial();
        if ( m.hasDiffuse() )   mat->setKd( m.m_diffuse );
        if ( m.hasSpecular() )  mat->setKs( m.m_specular );
        if ( m.hasShininess() ) mat->setNs( m.m_shininess );
#ifdef LOAD_TEXTURES
        if ( m.hasDiffuseTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_DIFFUSE, m.m_texDiffuse );
#endif
        //if ( m.hasSpecularTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SPECULAR, m.m_texSpecular );
        //if ( m.hasShininessTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SHININESS, m.m_texShininess );
        //if ( m.hasOpacityTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_ALPHA, m.m_texOpacity );
        //if ( m.hasNormalTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_NORMAL, m.m_texNormal );

        rt->material = mat;
        rt->shaderConfig = Ra::Engine::ShaderConfiguration( "BlinnPhong", "../Shaders" );

        renderObject->setRenderTechnique( rt );
    }

    Ra::Core::Index FancyMeshComponent::getRenderObjectIndex() const
    {
        return m_meshIndex;
    }

    const Ra::Core::TriangleMesh& FancyMeshComponent::getMesh() const
    {
        return getDisplayMesh().getGeometry();
    }

    void FancyMeshComponent::setupIO(const std::string& id)
    {
        Ra::Engine::ComponentMessenger::GetterCallback cbOut = std::bind( &FancyMeshComponent::getMeshOutput, this );
        Ra::Engine::ComponentMessenger::getInstance()->registerOutput<Ra::Core::TriangleMesh>( getEntity(), this, id, cbOut);

        if( m_deformable)
        {
            ComponentMessenger::SetterCallback cbIn = std::bind( &FancyMeshComponent::setMeshInput, this, std::placeholders::_1 );
            ComponentMessenger::getInstance()->registerInput<Ra::Core::TriangleMesh>( getEntity(), this, id, cbIn);

            ComponentMessenger::ReadWriteCallback vRW = std::bind( &FancyMeshComponent::getVerticesRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"v", vRW);

            ComponentMessenger::ReadWriteCallback nRW = std::bind( &FancyMeshComponent::getNormalsRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"n", nRW);

            ComponentMessenger::ReadWriteCallback tRW = std::bind( &FancyMeshComponent::getTrianglesRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"t", tRW);
        }

    }

    const Ra::Engine::Mesh& FancyMeshComponent::getDisplayMesh() const
    {
        return *(getRoMgr()->getRenderObject(getRenderObjectIndex())->getMesh());
    }

    Ra::Engine::Mesh& FancyMeshComponent::getDisplayMesh()
    {
        return *(getRoMgr()->getRenderObject(getRenderObjectIndex())->getMesh());
    }

    const void* FancyMeshComponent::getMeshOutput() const
    {
        return &(getMesh());
    }

    void FancyMeshComponent::setMeshInput(const void *meshptr)
    {

        CORE_ASSERT( meshptr, " Input is null");
        CORE_ASSERT( m_deformable, "Mesh is not deformable");

        Ra::Core::TriangleMesh mesh = *(static_cast<const Ra::Core::TriangleMesh*>(meshptr));

        Ra::Engine::Mesh& displayMesh = getDisplayMesh();
        displayMesh.loadGeometry( mesh );
    }

    void* FancyMeshComponent::getVerticesRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::VERTEX_POSITION);
        return &(getDisplayMesh().getGeometry().m_vertices);
    }

    void* FancyMeshComponent::getNormalsRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::VERTEX_NORMAL);
        return &(getDisplayMesh().getGeometry().m_normals);
    }

    void* FancyMeshComponent::getTrianglesRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::INDEX);
        return &(getDisplayMesh().getGeometry().m_triangles);
    }

    void FancyMeshComponent::rayCastQuery( const Ra::Core::Ray& r) const
    {
        auto result  = Ra::Core::MeshUtils::castRay( getMesh(), r );
        int tidx = result.m_hitTriangle;
        if (tidx >= 0)
        {
            LOG(logINFO) << " Hit triangle " << tidx;
            LOG(logINFO) << " Nearest vertex " << result.m_nearestVertex;
        }
    }

} // namespace FancyMeshPlugin
<commit_msg>normals are recomputed again after loading.<commit_after>#include <FancyMeshComponent.hpp>

#include <iostream>

#include <Core/String/StringUtils.hpp>
#include <Core/Mesh/MeshUtils.hpp>

#include <Core/Geometry/Normal/Normal.hpp>

#include <Engine/Renderer/RenderObject/RenderObjectManager.hpp>
#include <Engine/Managers/ComponentMessenger/ComponentMessenger.hpp>

#include <Engine/Renderer/Mesh/Mesh.hpp>
#include <Engine/Renderer/RenderObject/RenderObject.hpp>
#include <Engine/Renderer/RenderObject/RenderObjectTypes.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderConfiguration.hpp>
#include <Engine/Renderer/RenderTechnique/ShaderProgramManager.hpp>
#include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>

#include <Engine/Assets/FileData.hpp>
#include <Engine/Assets/GeometryData.hpp>

using Ra::Engine::ComponentMessenger;

namespace FancyMeshPlugin
{
    FancyMeshComponent::FancyMeshComponent(const std::string& name , bool deformable)
        : Ra::Engine::Component( name  ) , m_deformable(deformable)
    {
    }

    FancyMeshComponent::~FancyMeshComponent()
    {
    }

    void FancyMeshComponent::initialize()
    {
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh, const std::string& name )
    {
        Ra::Engine::RenderTechnique* technique = new Ra::Engine::RenderTechnique;
        technique->material = new Ra::Engine::Material( "Default" );
        technique->shaderConfig = Ra::Engine::ShaderConfiguration( "Default", "../Shaders" );

        addMeshRenderObject(mesh, name, technique);
    }

    void FancyMeshComponent::addMeshRenderObject( const Ra::Core::TriangleMesh& mesh,
                                                  const std::string& name,
                                                  Ra::Engine::RenderTechnique* technique )
    {
        setupIO(name);

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( name, this, Ra::Engine::RenderObjectType::Fancy );
        renderObject->setVisible( true );
        renderObject->setRenderTechnique( technique );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( name ) );
        displayMesh->loadGeometry( mesh );
        renderObject->setMesh( displayMesh );
        addRenderObject( renderObject );
    }

    void FancyMeshComponent::handleMeshLoading( const Ra::Asset::GeometryData* data )
    {
        std::string name( m_name );
        name.append( "_" + data->getName() );

        std::string roName = name;
        roName.append( "_RO" );

        std::string meshName = name;
        meshName.append( "_Mesh" );

        std::string matName = name;
        matName.append( "_Mat" );

        m_contentName = data->getName();

        Ra::Engine::RenderObject* renderObject = new Ra::Engine::RenderObject( roName, this, Ra::Engine::RenderObjectType::Fancy );
        renderObject->setVisible( true );

        std::shared_ptr<Ra::Engine::Mesh> displayMesh( new Ra::Engine::Mesh( meshName ) );

        Ra::Core::TriangleMesh mesh;
        for (size_t i = 0; i < data->getVerticesSize(); ++i)
        {
            mesh.m_vertices.push_back(data->getFrame() * data->getVertices()[i]);
//            mesh.m_normals.push_back(data->getNormals()[i]);
        }

        for (const auto& face : data->getFaces())
        {
            mesh.m_triangles.push_back(face.head<3>());
        }
        Ra::Core::Geometry::uniformNormal(mesh.m_vertices, mesh.m_triangles, mesh.m_normals);

        setupIO( data->getName());

        displayMesh->loadGeometry(mesh);

        Ra::Core::Vector3Array tangents;
        Ra::Core::Vector3Array bitangents;
        Ra::Core::Vector3Array texcoords;

        Ra::Core::Vector4Array colors;

        for ( const auto& v : data->getTangents() )     tangents.push_back( v );
        for ( const auto& v : data->getBiTangents() )   bitangents.push_back( v );
        for ( const auto& v : data->getTexCoords() )    texcoords.push_back( v );
        for ( const auto& v : data->getColors() )       colors.push_back( v );

        displayMesh->addData( Ra::Engine::Mesh::VERTEX_TANGENT, tangents );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_BITANGENT, bitangents );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_TEXCOORD, texcoords );
        displayMesh->addData( Ra::Engine::Mesh::VERTEX_COLOR, colors );
        // FIXME(Charly): Should not weights be part of the geometry ?
        //        mesh->addData( Ra::Engine::Mesh::VERTEX_WEIGHTS, meshData.weights );

        renderObject->setMesh( displayMesh );

        m_meshIndex = addRenderObject(renderObject);

        Ra::Engine::RenderTechnique* rt = new Ra::Engine::RenderTechnique;
        Ra::Engine::Material* mat = new Ra::Engine::Material( matName );
        auto m = data->getMaterial();
        if ( m.hasDiffuse() )   mat->setKd( m.m_diffuse );
        if ( m.hasSpecular() )  mat->setKs( m.m_specular );
        if ( m.hasShininess() ) mat->setNs( m.m_shininess );
#ifdef LOAD_TEXTURES
        if ( m.hasDiffuseTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_DIFFUSE, m.m_texDiffuse );
#endif
        //if ( m.hasSpecularTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SPECULAR, m.m_texSpecular );
        //if ( m.hasShininessTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_SHININESS, m.m_texShininess );
        //if ( m.hasOpacityTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_ALPHA, m.m_texOpacity );
        //if ( m.hasNormalTexture() ) mat->addTexture( Ra::Engine::Material::TextureType::TEX_NORMAL, m.m_texNormal );

        rt->material = mat;
        rt->shaderConfig = Ra::Engine::ShaderConfiguration( "BlinnPhong", "../Shaders" );

        renderObject->setRenderTechnique( rt );
    }

    Ra::Core::Index FancyMeshComponent::getRenderObjectIndex() const
    {
        return m_meshIndex;
    }

    const Ra::Core::TriangleMesh& FancyMeshComponent::getMesh() const
    {
        return getDisplayMesh().getGeometry();
    }

    void FancyMeshComponent::setupIO(const std::string& id)
    {
        Ra::Engine::ComponentMessenger::GetterCallback cbOut = std::bind( &FancyMeshComponent::getMeshOutput, this );
        Ra::Engine::ComponentMessenger::getInstance()->registerOutput<Ra::Core::TriangleMesh>( getEntity(), this, id, cbOut);

        if( m_deformable)
        {
            ComponentMessenger::SetterCallback cbIn = std::bind( &FancyMeshComponent::setMeshInput, this, std::placeholders::_1 );
            ComponentMessenger::getInstance()->registerInput<Ra::Core::TriangleMesh>( getEntity(), this, id, cbIn);

            ComponentMessenger::ReadWriteCallback vRW = std::bind( &FancyMeshComponent::getVerticesRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"v", vRW);

            ComponentMessenger::ReadWriteCallback nRW = std::bind( &FancyMeshComponent::getNormalsRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"n", nRW);

            ComponentMessenger::ReadWriteCallback tRW = std::bind( &FancyMeshComponent::getTrianglesRw, this);
            ComponentMessenger::getInstance()->registerReadWrite<Ra::Core::Vector3Array>( getEntity(), this, id+"t", tRW);
        }

    }

    const Ra::Engine::Mesh& FancyMeshComponent::getDisplayMesh() const
    {
        return *(getRoMgr()->getRenderObject(getRenderObjectIndex())->getMesh());
    }

    Ra::Engine::Mesh& FancyMeshComponent::getDisplayMesh()
    {
        return *(getRoMgr()->getRenderObject(getRenderObjectIndex())->getMesh());
    }

    const void* FancyMeshComponent::getMeshOutput() const
    {
        return &(getMesh());
    }

    void FancyMeshComponent::setMeshInput(const void *meshptr)
    {

        CORE_ASSERT( meshptr, " Input is null");
        CORE_ASSERT( m_deformable, "Mesh is not deformable");

        Ra::Core::TriangleMesh mesh = *(static_cast<const Ra::Core::TriangleMesh*>(meshptr));

        Ra::Engine::Mesh& displayMesh = getDisplayMesh();
        displayMesh.loadGeometry( mesh );
    }

    void* FancyMeshComponent::getVerticesRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::VERTEX_POSITION);
        return &(getDisplayMesh().getGeometry().m_vertices);
    }

    void* FancyMeshComponent::getNormalsRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::VERTEX_NORMAL);
        return &(getDisplayMesh().getGeometry().m_normals);
    }

    void* FancyMeshComponent::getTrianglesRw()
    {
        getDisplayMesh().setDirty( Ra::Engine::Mesh::INDEX);
        return &(getDisplayMesh().getGeometry().m_triangles);
    }

    void FancyMeshComponent::rayCastQuery( const Ra::Core::Ray& r) const
    {
        auto result  = Ra::Core::MeshUtils::castRay( getMesh(), r );
        int tidx = result.m_hitTriangle;
        if (tidx >= 0)
        {
            LOG(logINFO) << " Hit triangle " << tidx;
            LOG(logINFO) << " Nearest vertex " << result.m_nearestVertex;
        }
    }

} // namespace FancyMeshPlugin
<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2020 Intel Corporation

#ifdef HAVE_INF_ENGINE

#include <vector>
#include <string>
#include <tuple>

#include "backends/ie/giebackend/giewrapper.hpp"

#include <ade/util/range.hpp>
#include <ade/util/zip_range.hpp>

#include <opencv2/core/utility.hpp>
#include <opencv2/core/utils/logger.hpp>

namespace IE = InferenceEngine;
namespace giewrap = cv::gimpl::ie::wrap;
using GIEParam = cv::gapi::ie::detail::ParamDesc;

IE::InputsDataMap giewrap::toInputsDataMap (const IE::ConstInputsDataMap& inputs) {
    IE::InputsDataMap transformed;
    auto convert = [](const std::pair<std::string, IE::InputInfo::CPtr>& p) {
        return std::make_pair(p.first, std::const_pointer_cast<IE::InputInfo>(p.second));
    };
    std::transform(inputs.begin(), inputs.end(), std::inserter(transformed, transformed.end()), convert);
    return transformed;
}

IE::OutputsDataMap giewrap::toOutputsDataMap (const IE::ConstOutputsDataMap& outputs) {
    IE::OutputsDataMap transformed;
    auto convert = [](const std::pair<std::string, IE::CDataPtr>& p) {
        return std::make_pair(p.first, std::const_pointer_cast<IE::Data>(p.second));
    };
    std::transform(outputs.begin(), outputs.end(), std::inserter(transformed, transformed.end()), convert);
    return transformed;
}

#if INF_ENGINE_RELEASE < 2020000000  // < 2020.1
// Load extensions (taken from DNN module)
std::vector<std::string> giewrap::getExtensions(const GIEParam& params) {
    std::vector<std::string> candidates;
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        const std::string suffixes[] = { "_avx2", "_sse4", ""};
        const bool haveFeature[] = {
            cv::checkHardwareSupport(CPU_AVX2),
            cv::checkHardwareSupport(CPU_SSE4_2),
            true
        };
        for (auto &&it : ade::util::zip(ade::util::toRange(suffixes),
                                        ade::util::toRange(haveFeature)))
        {
            std::string suffix;
            bool available = false;
            std::tie(suffix, available) = it;
            if (!available) continue;
#ifdef _WIN32
            candidates.push_back("cpu_extension" + suffix + ".dll");
#elif defined(__APPLE__)
            candidates.push_back("libcpu_extension" + suffix + ".so");  // built as loadable module
            candidates.push_back("libcpu_extension" + suffix + ".dylib");  // built as shared library
#else
            candidates.push_back("libcpu_extension" + suffix + ".so");
#endif  // _WIN32
        }
    }
    return candidates;
}

IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
    IE::CNNNetReader reader;
    reader.ReadNetwork(params.model_path);
    reader.ReadWeights(params.weights_path);
    return reader.getNetwork();
}
#else // >= 2020.1
std::vector<std::string> giewrap::getExtensions(const GIEParam&) {
    return std::vector<std::string>();
}

IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
    auto core = giewrap::getCore();
    return core.ReadNetwork(params.model_path, params.weights_path);
}
#endif // INF_ENGINE_RELEASE < 2020000000

#if INF_ENGINE_RELEASE < 2019020000  // < 2019.R2
IE::InferencePlugin giewrap::getPlugin(const GIEParam& params) {
    auto plugin = IE::PluginDispatcher().getPluginByDevice(params.device_id);
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        for (auto &&extlib : giewrap::getExtensions(params))
        {
            try
            {
                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib));
                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
                break;
            }
            catch(...)
            {
                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
            }
        }
    }
    return plugin;
}
#else // >= 2019.R2
IE::Core giewrap::getCore() {
    static IE::Core core;
    return core;
}

IE::Core giewrap::getPlugin(const GIEParam& params) {
    auto plugin = giewrap::getCore();
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        for (auto &&extlib : giewrap::getExtensions(params))
        {
            try
            {
                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib), params.device_id);
                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
                break;
            }
            catch(...)
            {
                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
            }
        }
    }
    return plugin;
}
#endif // INF_ENGINE_RELEASE < 2019020000

#endif //HAVE_INF_ENGINE
<commit_msg>gapi(ie): replace deprecated calls<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2020 Intel Corporation

#ifdef HAVE_INF_ENGINE

#include <vector>
#include <string>
#include <tuple>

#include "backends/ie/giebackend/giewrapper.hpp"

#include <ade/util/range.hpp>
#include <ade/util/zip_range.hpp>

#include <opencv2/core/utility.hpp>
#include <opencv2/core/utils/logger.hpp>

namespace IE = InferenceEngine;
namespace giewrap = cv::gimpl::ie::wrap;
using GIEParam = cv::gapi::ie::detail::ParamDesc;

IE::InputsDataMap giewrap::toInputsDataMap (const IE::ConstInputsDataMap& inputs) {
    IE::InputsDataMap transformed;
    auto convert = [](const std::pair<std::string, IE::InputInfo::CPtr>& p) {
        return std::make_pair(p.first, std::const_pointer_cast<IE::InputInfo>(p.second));
    };
    std::transform(inputs.begin(), inputs.end(), std::inserter(transformed, transformed.end()), convert);
    return transformed;
}

IE::OutputsDataMap giewrap::toOutputsDataMap (const IE::ConstOutputsDataMap& outputs) {
    IE::OutputsDataMap transformed;
    auto convert = [](const std::pair<std::string, IE::CDataPtr>& p) {
        return std::make_pair(p.first, std::const_pointer_cast<IE::Data>(p.second));
    };
    std::transform(outputs.begin(), outputs.end(), std::inserter(transformed, transformed.end()), convert);
    return transformed;
}

#if INF_ENGINE_RELEASE < 2020000000  // < 2020.1
// Load extensions (taken from DNN module)
std::vector<std::string> giewrap::getExtensions(const GIEParam& params) {
    std::vector<std::string> candidates;
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        const std::string suffixes[] = { "_avx2", "_sse4", ""};
        const bool haveFeature[] = {
            cv::checkHardwareSupport(CPU_AVX2),
            cv::checkHardwareSupport(CPU_SSE4_2),
            true
        };
        for (auto &&it : ade::util::zip(ade::util::toRange(suffixes),
                                        ade::util::toRange(haveFeature)))
        {
            std::string suffix;
            bool available = false;
            std::tie(suffix, available) = it;
            if (!available) continue;
#ifdef _WIN32
            candidates.push_back("cpu_extension" + suffix + ".dll");
#elif defined(__APPLE__)
            candidates.push_back("libcpu_extension" + suffix + ".so");  // built as loadable module
            candidates.push_back("libcpu_extension" + suffix + ".dylib");  // built as shared library
#else
            candidates.push_back("libcpu_extension" + suffix + ".so");
#endif  // _WIN32
        }
    }
    return candidates;
}

IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
    IE::CNNNetReader reader;
    reader.ReadNetwork(params.model_path);
    reader.ReadWeights(params.weights_path);
    return reader.getNetwork();
}
#else // >= 2020.1
std::vector<std::string> giewrap::getExtensions(const GIEParam&) {
    return std::vector<std::string>();
}

IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
    auto core = giewrap::getCore();
    return core.ReadNetwork(params.model_path, params.weights_path);
}
#endif // INF_ENGINE_RELEASE < 2020000000

#if INF_ENGINE_RELEASE < 2019020000  // < 2019.R2
IE::InferencePlugin giewrap::getPlugin(const GIEParam& params) {
    auto plugin = IE::PluginDispatcher().getPluginByDevice(params.device_id);
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        for (auto &&extlib : giewrap::getExtensions(params))
        {
            try
            {
                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib));
                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
                break;
            }
            catch(...)
            {
                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
            }
        }
    }
    return plugin;
}
#else // >= 2019.R2
IE::Core giewrap::getCore() {
    static IE::Core core;
    return core;
}

IE::Core giewrap::getPlugin(const GIEParam& params) {
    auto plugin = giewrap::getCore();
    if (params.device_id == "CPU" || params.device_id == "FPGA")
    {
        for (auto &&extlib : giewrap::getExtensions(params))
        {
            try
            {
#if INF_ENGINE_RELEASE >= 2021040000
                plugin.AddExtension(std::make_shared<IE::Extension>(extlib), params.device_id);
#else
                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib), params.device_id);
#endif
                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
                break;
            }
            catch(...)
            {
                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
            }
        }
    }
    return plugin;
}
#endif // INF_ENGINE_RELEASE < 2019020000

#endif //HAVE_INF_ENGINE
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/core/text/ParagraphBuilder.h"

#include "sky/engine/core/rendering/PaintInfo.h"
#include "sky/engine/core/rendering/style/RenderStyle.h"
#include "sky/engine/platform/fonts/FontCache.h"
#include "sky/engine/platform/graphics/GraphicsContext.h"

namespace blink {

Paragraph::Paragraph(PassOwnPtr<RenderView> renderView)
    : m_renderView(renderView)
{
}

Paragraph::~Paragraph()
{
}

double Paragraph::width()
{
    return firstChildBox()->width();
}

double Paragraph::height()
{
    return firstChildBox()->height();
}

double Paragraph::minIntrinsicWidth()
{
    return firstChildBox()->minPreferredLogicalWidth();
}

double Paragraph::maxIntrinsicWidth()
{
    return firstChildBox()->maxPreferredLogicalWidth();
}

double Paragraph::alphabeticBaseline()
{
    return firstChildBox()->firstLineBoxBaseline(FontBaselineOrAuto(AlphabeticBaseline));
}

double Paragraph::ideographicBaseline()
{
    return firstChildBox()->firstLineBoxBaseline(FontBaselineOrAuto(IdeographicBaseline));
}

void Paragraph::layout()
{
    FontCachePurgePreventer fontCachePurgePreventer;

    LayoutUnit maxWidth = std::max(m_minWidth, m_maxWidth);
    LayoutUnit maxHeight = std::max(m_minHeight, m_maxHeight);
    m_renderView->setFrameViewSize(IntSize(maxWidth, maxHeight));
    m_renderView->layout();
}

void Paragraph::paint(Canvas* canvas, const Offset& offset)
{
    FontCachePurgePreventer fontCachePurgePreventer;

    // Very simplified painting to allow painting an arbitrary (layer-less) subtree.
    RenderBox* box = firstChildBox();
    GraphicsContext context(canvas->skCanvas());

    Vector<RenderBox*> layers;
    LayoutPoint paintOffset(offset.sk_size.width(), offset.sk_size.height());
    LayoutRect bounds = box->absoluteBoundingBoxRect();
    DCHECK(bounds.x() == 0 && bounds.y() == 0);
    bounds.setLocation(paintOffset);
    PaintInfo paintInfo(&context, enclosingIntRect(bounds), box);
    box->paint(paintInfo, paintOffset, layers);

    // Note we're ignoring any layers encountered.
    // TODO(abarth): Remove the concept of RenderLayers.
}

} // namespace blink
<commit_msg>Text snaps to pixel grid, images don't<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/core/text/ParagraphBuilder.h"

#include "sky/engine/core/rendering/PaintInfo.h"
#include "sky/engine/core/rendering/style/RenderStyle.h"
#include "sky/engine/platform/fonts/FontCache.h"
#include "sky/engine/platform/graphics/GraphicsContext.h"

namespace blink {

Paragraph::Paragraph(PassOwnPtr<RenderView> renderView)
    : m_renderView(renderView)
{
}

Paragraph::~Paragraph()
{
}

double Paragraph::width()
{
    return firstChildBox()->width();
}

double Paragraph::height()
{
    return firstChildBox()->height();
}

double Paragraph::minIntrinsicWidth()
{
    return firstChildBox()->minPreferredLogicalWidth();
}

double Paragraph::maxIntrinsicWidth()
{
    return firstChildBox()->maxPreferredLogicalWidth();
}

double Paragraph::alphabeticBaseline()
{
    return firstChildBox()->firstLineBoxBaseline(FontBaselineOrAuto(AlphabeticBaseline));
}

double Paragraph::ideographicBaseline()
{
    return firstChildBox()->firstLineBoxBaseline(FontBaselineOrAuto(IdeographicBaseline));
}

void Paragraph::layout()
{
    FontCachePurgePreventer fontCachePurgePreventer;

    LayoutUnit maxWidth = std::max(m_minWidth, m_maxWidth);
    LayoutUnit maxHeight = std::max(m_minHeight, m_maxHeight);
    m_renderView->setFrameViewSize(IntSize(maxWidth, maxHeight));
    m_renderView->layout();
}

void Paragraph::paint(Canvas* canvas, const Offset& offset)
{
    FontCachePurgePreventer fontCachePurgePreventer;

    // Very simplified painting to allow painting an arbitrary (layer-less) subtree.
    RenderBox* box = firstChildBox();
    SkCanvas* skCanvas = canvas->skCanvas();
    skCanvas->translate(offset.sk_size.width(), offset.sk_size.height());

    GraphicsContext context(skCanvas);
    Vector<RenderBox*> layers;
    LayoutRect bounds = box->absoluteBoundingBoxRect();
    DCHECK(bounds.x() == 0 && bounds.y() == 0);
    PaintInfo paintInfo(&context, enclosingIntRect(bounds), box);
    box->paint(paintInfo, LayoutPoint(), layers);
    // Note we're ignoring any layers encountered.
    // TODO(abarth): Remove the concept of RenderLayers.

    skCanvas->translate(-offset.sk_size.width(), -offset.sk_size.height());
}

} // namespace blink
<|endoftext|>


<commit_before>#include "frequencymap.h"

#include "math.h"

FrequencyMap::FrequencyMap()
{
    // temperaments
    temperaments.append({"12-edo (standard)", EqualTemperament, 12.0 });
    temperaments.append({"Syntonic (5-TET)", SyntonicTemperament, pow(2.0, 3.0 / 5.0) });
    temperaments.append({"Syntonic (22-TET)", SyntonicTemperament, pow(2.0, 13.0 / 22.0) });
    temperaments.append({"Syntonic (17-TET)", SyntonicTemperament, pow(2.0, 10.0 / 17.0) });
    temperaments.append({"Syntonic (Pythagorean)", SyntonicTemperament, 1.5 });
    temperaments.append({"Syntonic (12-TET)", SyntonicTemperament, pow(2.0, 7.0 / 12.0) });
    temperaments.append({"Syntonic (43-TET, 1/5 Comma)", SyntonicTemperament, pow(2.0, 25.0 / 43.0) });
    temperaments.append({"Syntonic (31-TET, 1/4 Comma)", SyntonicTemperament, pow(2.0, 18.0 / 31.0) });
    temperaments.append({"Syntonic (50-TET, 2/7 Comma)", SyntonicTemperament, pow(2.0, 29.0 / 50.0) });
    temperaments.append({"Syntonic (19-TET, 1/3 Comma)", SyntonicTemperament, pow(2.0, 11.0 / 19.0) });
    temperaments.append({"Syntonic (26-TET)", SyntonicTemperament, pow(2.0, 15.0 / 26.0) });
    temperaments.append({"Syntonic (7-TET)", SyntonicTemperament, pow(2.0, 4.0 / 7.0) });
    temperaments.append({"Just 5-limit (Symmetric 1 Aug 4th)", JustTemperament, 0 });
    temperaments.append({"Just 5-limit (Symmetric 1 Dim 5th)", JustTemperament, 1 });
    temperaments.append({"Just 5-limit (Symmetric 2 Aug 4th)", JustTemperament, 2 });
    temperaments.append({"Just 5-limit (Symmetric 2 Dim 5th)", JustTemperament, 3 });
    temperaments.append({"Just 5-limit (Asymmetric Standard Aug 4th)", JustTemperament, 4 });
    temperaments.append({"Just 5-limit (Asymmetric Standard Dim 5th)", JustTemperament, 5 });
    temperaments.append({"Just 5-limit (Asymmetric Extended Aug 4th)", JustTemperament, 6 });
    temperaments.append({"Just 5-limit (Asymmetric Extended Dim 5th)", JustTemperament, 7 });
    temperaments.append({"Just 7-limit (Aug 4th)", JustTemperament, 8 });
    temperaments.append({"Just 7-limit (Dim 5th)", JustTemperament, 9 });
    temperaments.append({"Just 17-limit (Aug 4th)", JustTemperament, 10 });
    temperaments.append({"Just 17-limit (Dim 5th)", JustTemperament, 11 });

    // scales
    scales.append({"Banjo (standard)", {"G4","D3","G3","B3","D4"}});
    scales.append({"Bass Guitar (standard)", {"E1","A1","D2","G2"}});
    scales.append({"Cello (standard)", {"C2","G2","D3","A3"}});
    scales.append({"Guitar (standard)", {"E2","A2","D3","G3","B3","E4"}});
    scales.append({"Mandolin", {"G3","D4","A4","E5"}});
    scales.append({"Ukelele (Concert)", {"G4","C4","E4","A4"}});
    scales.append({"Violin", {"G3","D4","A4","E5"}});
    scales.append({"Chromatic 1", {"A1","A#1","B1","C1","C#1","D1","D#1","E1","F1","G1","G#1"}});
    scales.append({"Chromatic 2", {"A2","A#2","B2","C2","C#2","D2","D#2","E2","F2","G2","G#2"}});
    scales.append({"Chromatic 3", {"A3","A#3","B3","C3","C#3","D3","D#3","E3","F3","G3","G#3"}});
    scales.append({"Chromatic 4", {"A4","A#4","B4","C4","C#4","D4","D#4","E4","F4","G4","G#4"}});
    scales.append({"Chromatic 5", {"A5","A#5","B5","C5","C#5","D5","D#5","E5","F5","G5","G#5"}});
    scales.append({"Chromatic 6", {"A6","A#6","B6","C6","C#6","D6","D#6","E6","F6","G6","G#6"}});

    // pitch names
    QList<QString> octaves({"0", "1", "2", "3", "4", "5", "6", "7", "8"});
    QList<QString> sharps({"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"});
    QList<QString> flats({"A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab"});
    QString name;
    int num = 21; // the MIDI note number for A0
    for (int oct = 0; oct < octaves.length(); oct++) {
        for (int i = 0; i < sharps.length(); i++) {
            if (sharps.at(i) == flats.at(i)) {
                name = sharps.at(i) + octaves.at(oct);
                pitchNames.append(name);
                pitches.insert(name, num);
            }
            else {
                name = sharps.at(i) + "/" + flats.at(i) + octaves.at(oct);
                pitchNames.append(name);
                pitches.insert(name, num);
                pitches.insert(sharps.at(i) + octaves.at(oct), num);
                pitches.insert(flats.at(i) + octaves.at(oct), num);
            }
            num++;
        }
    }

    // set defaults to 12-edo at A4 = 440.0 Hz
    temperamentIndex = 0;
    refPitch = 69;
    refFreq = 440.0;

    // populate frequencies
    updateFrequencies();
}

void FrequencyMap::updateFrequencies()
{
    int p;
    Temperament temp = temperaments[temperamentIndex];
    // set the reference pitch
    frequencies[refPitch] = refFreq;
    // build the octave above the reference pitch
    if (temp.type == EqualTemperament) {
        // in equal temperament the parameter is the number of divisions of the octave,
        //  which should generally be 12 since we have 12 pitch classes
        float divisions = temp.param;
        for (p = 1; p < 12; p++) {
            frequencies[refPitch + p] =
                refFreq * pow(2.0, (float)p / divisions);
        }
    }
    else if (temp.type == SyntonicTemperament) {
        // in syntonic temperaments the parameter is the ratio of a perfect fifth
        float Fr = temp.param;
        float Or = 2.0;
        frequencies[refPitch+1]  = refFreq * (pow(Fr, 7)  / pow(Or, 4));
        frequencies[refPitch+2]  = refFreq * (pow(Fr, 2)  / pow(Or, 2));
        frequencies[refPitch+3]  = refFreq * (pow(Fr, 9)  / pow(Or, 5));
        frequencies[refPitch+4]  = refFreq * (pow(Fr, 4)  / pow(Or, 2));
        frequencies[refPitch+5]  = refFreq * (pow(Fr, 11) / pow(Or, 6));
        frequencies[refPitch+6]  = refFreq * (pow(Fr, 6)  / pow(Or, 3));
        frequencies[refPitch+7]  = refFreq * Fr;
        frequencies[refPitch+8]  = refFreq * (pow(Fr, 8)  / pow(Or, 4));
        frequencies[refPitch+9]  = refFreq * (pow(Fr, 3)  / pow(Or, 2));
        frequencies[refPitch+10] = refFreq * (pow(Fr, 10) / pow(Or, 5));
        frequencies[refPitch+11] = refFreq * (pow(Fr, 5)  / pow(Or, 2));
    }
    else if (temp.type == JustTemperament) {
        // in just temperaments the parameter is an index into the ratio table
        int ri = (int)temp.param;
        for (p = 0; p < 11; p++) {
            frequencies[refPitch+p+1] = refFreq *
                ((float)justRatios[ri][p][0] / (float)justRatios[ri][p][1]);
        }
    }
    // fill in the other octaves by doubling and halving
    for (p = refPitch + 12; p < 128; p++) {
        frequencies[p] = frequencies[p - 12] * 2.0;
    }
    for (p = refPitch - 1; p >= 0; p--) {
        frequencies[p] = frequencies[p + 12] * 0.5;
    }
}
<commit_msg>fix octave numbering<commit_after>#include "frequencymap.h"

#include "math.h"

FrequencyMap::FrequencyMap()
{
    // temperaments
    temperaments.append({"12-edo (standard)", EqualTemperament, 12.0 });
    temperaments.append({"Syntonic (5-TET)", SyntonicTemperament, pow(2.0, 3.0 / 5.0) });
    temperaments.append({"Syntonic (22-TET)", SyntonicTemperament, pow(2.0, 13.0 / 22.0) });
    temperaments.append({"Syntonic (17-TET)", SyntonicTemperament, pow(2.0, 10.0 / 17.0) });
    temperaments.append({"Syntonic (Pythagorean)", SyntonicTemperament, 1.5 });
    temperaments.append({"Syntonic (12-TET)", SyntonicTemperament, pow(2.0, 7.0 / 12.0) });
    temperaments.append({"Syntonic (43-TET, 1/5 Comma)", SyntonicTemperament, pow(2.0, 25.0 / 43.0) });
    temperaments.append({"Syntonic (31-TET, 1/4 Comma)", SyntonicTemperament, pow(2.0, 18.0 / 31.0) });
    temperaments.append({"Syntonic (50-TET, 2/7 Comma)", SyntonicTemperament, pow(2.0, 29.0 / 50.0) });
    temperaments.append({"Syntonic (19-TET, 1/3 Comma)", SyntonicTemperament, pow(2.0, 11.0 / 19.0) });
    temperaments.append({"Syntonic (26-TET)", SyntonicTemperament, pow(2.0, 15.0 / 26.0) });
    temperaments.append({"Syntonic (7-TET)", SyntonicTemperament, pow(2.0, 4.0 / 7.0) });
    temperaments.append({"Just 5-limit (Symmetric 1 Aug 4th)", JustTemperament, 0 });
    temperaments.append({"Just 5-limit (Symmetric 1 Dim 5th)", JustTemperament, 1 });
    temperaments.append({"Just 5-limit (Symmetric 2 Aug 4th)", JustTemperament, 2 });
    temperaments.append({"Just 5-limit (Symmetric 2 Dim 5th)", JustTemperament, 3 });
    temperaments.append({"Just 5-limit (Asymmetric Standard Aug 4th)", JustTemperament, 4 });
    temperaments.append({"Just 5-limit (Asymmetric Standard Dim 5th)", JustTemperament, 5 });
    temperaments.append({"Just 5-limit (Asymmetric Extended Aug 4th)", JustTemperament, 6 });
    temperaments.append({"Just 5-limit (Asymmetric Extended Dim 5th)", JustTemperament, 7 });
    temperaments.append({"Just 7-limit (Aug 4th)", JustTemperament, 8 });
    temperaments.append({"Just 7-limit (Dim 5th)", JustTemperament, 9 });
    temperaments.append({"Just 17-limit (Aug 4th)", JustTemperament, 10 });
    temperaments.append({"Just 17-limit (Dim 5th)", JustTemperament, 11 });

    // scales
    scales.append({"Banjo (standard)", {"G4","D3","G3","B3","D4"}});
    scales.append({"Bass Guitar (standard)", {"E1","A1","D2","G2"}});
    scales.append({"Cello (standard)", {"C2","G2","D3","A3"}});
    scales.append({"Guitar (standard)", {"E2","A2","D3","G3","B3","E4"}});
    scales.append({"Mandolin", {"G3","D4","A4","E5"}});
    scales.append({"Ukelele (Concert)", {"G4","C4","E4","A4"}});
    scales.append({"Violin", {"G3","D4","A4","E5"}});
    scales.append({"Chromatic 1", {"C1","C#1","D1","D#1","E1","F1","G1","G#1","A1","A#1","B1"}});
    scales.append({"Chromatic 2", {"C2","C#2","D2","D#2","E2","F2","G2","G#2","A2","A#2","B2"}});
    scales.append({"Chromatic 3", {"C3","C#3","D3","D#3","E3","F3","G3","G#3","A3","A#3","B3"}});
    scales.append({"Chromatic 4", {"C4","C#4","D4","D#4","E4","F4","G4","G#4","A4","A#4","B4"}});
    scales.append({"Chromatic 5", {"C5","C#5","D5","D#5","E5","F5","G5","G#5","A5","A#5","B5"}});
    scales.append({"Chromatic 6", {"C6","C#6","D6","D#6","E6","F6","G6","G#6","A6","A#6","B6"}});

    // pitch names
    QList<QString> octaves({"0", "1", "2", "3", "4", "5", "6", "7", "8"});
    QList<QString> sharps({"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"});
    QList<QString> flats({"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"});
    QString name;
    int num = 12; // the MIDI note number for C0
    for (int oct = 0; oct < octaves.length(); oct++) {
        for (int i = 0; i < sharps.length(); i++) {
            if (sharps.at(i) == flats.at(i)) {
                name = sharps.at(i) + octaves.at(oct);
                pitchNames.append(name);
                pitches.insert(name, num);
            }
            else {
                name = sharps.at(i) + "/" + flats.at(i) + octaves.at(oct);
                pitchNames.append(name);
                pitches.insert(name, num);
                pitches.insert(sharps.at(i) + octaves.at(oct), num);
                pitches.insert(flats.at(i) + octaves.at(oct), num);
            }
            num++;
        }
    }

    // set defaults to 12-edo at A4 = 440.0 Hz
    temperamentIndex = 0;
    refPitch = 69;
    refFreq = 440.0;

    // populate frequencies
    updateFrequencies();
}

void FrequencyMap::updateFrequencies()
{
    int p;
    Temperament temp = temperaments[temperamentIndex];
    // set the reference pitch
    frequencies[refPitch] = refFreq;
    // build the octave above the reference pitch
    if (temp.type == EqualTemperament) {
        // in equal temperament the parameter is the number of divisions of the octave,
        //  which should generally be 12 since we have 12 pitch classes
        float divisions = temp.param;
        for (p = 1; p < 12; p++) {
            frequencies[refPitch + p] =
                refFreq * pow(2.0, (float)p / divisions);
        }
    }
    else if (temp.type == SyntonicTemperament) {
        // in syntonic temperaments the parameter is the ratio of a perfect fifth
        float Fr = temp.param;
        float Or = 2.0;
        frequencies[refPitch+1]  = refFreq * (pow(Fr, 7)  / pow(Or, 4));
        frequencies[refPitch+2]  = refFreq * (pow(Fr, 2)  / pow(Or, 2));
        frequencies[refPitch+3]  = refFreq * (pow(Fr, 9)  / pow(Or, 5));
        frequencies[refPitch+4]  = refFreq * (pow(Fr, 4)  / pow(Or, 2));
        frequencies[refPitch+5]  = refFreq * (pow(Fr, 11) / pow(Or, 6));
        frequencies[refPitch+6]  = refFreq * (pow(Fr, 6)  / pow(Or, 3));
        frequencies[refPitch+7]  = refFreq * Fr;
        frequencies[refPitch+8]  = refFreq * (pow(Fr, 8)  / pow(Or, 4));
        frequencies[refPitch+9]  = refFreq * (pow(Fr, 3)  / pow(Or, 2));
        frequencies[refPitch+10] = refFreq * (pow(Fr, 10) / pow(Or, 5));
        frequencies[refPitch+11] = refFreq * (pow(Fr, 5)  / pow(Or, 2));
    }
    else if (temp.type == JustTemperament) {
        // in just temperaments the parameter is an index into the ratio table
        int ri = (int)temp.param;
        for (p = 0; p < 11; p++) {
            frequencies[refPitch+p+1] = refFreq *
                ((float)justRatios[ri][p][0] / (float)justRatios[ri][p][1]);
        }
    }
    // fill in the other octaves by doubling and halving
    for (p = refPitch + 12; p < 128; p++) {
        frequencies[p] = frequencies[p - 12] * 2.0;
    }
    for (p = refPitch - 1; p >= 0; p--) {
        frequencies[p] = frequencies[p + 12] * 0.5;
    }
}
<|endoftext|>


<commit_before>#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <streambuf>

#include <emscripten.h>

#include "html5_resource.h"

html5_resource::~html5_resource()
{
}

std::string html5_resource::get_text_resource(const std::string& name) const
{
    std::cout << "html5_resource::get_text_resource " << name << std::endl;

    std::stringstream sstream;
    sstream << name;

    const std::string filepath(sstream.str());

    std::ifstream t(filepath);
    std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

    return str;
}

void html5_resource::save_text_data(const std::string& name, const std::string& data)
{
    std::cout << "html5_resource::save_text_data" << std::endl;

    EM_ASM_ARGS({
        var name_str = Pointer_stringify($0);
        var data_str = Pointer_stringify($1);

        localStorage.setItem(name_str, data_str);
    }, name.c_str(), data.c_str());
}

std::string html5_resource::load_text_data(const std::string& name) const
{
    std::cout << "html5_resource::load_text_data" << std::endl;

    /*
        var item = localStorage.getItem(key);
        if(item == null) {
            return "";
        }
        return item;
    */
    return "";
}
<commit_msg>Impl HTML5 html5_resource::load_text_data<commit_after>#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <streambuf>

#include <emscripten.h>

#include "html5_resource.h"

html5_resource::~html5_resource()
{
}

std::string html5_resource::get_text_resource(const std::string& name) const
{
    std::cout << "html5_resource::get_text_resource " << name << std::endl;

    std::stringstream sstream;
    sstream << name;

    const std::string filepath(sstream.str());

    std::ifstream t(filepath);
    std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

    return str;
}

void html5_resource::save_text_data(const std::string& name, const std::string& data)
{
    std::cout << "html5_resource::save_text_data " << name << std::endl;

    EM_ASM_ARGS({
        var name_str = Pointer_stringify($0);
        var data_str = Pointer_stringify($1);

        localStorage.setItem(name_str, data_str);
    }, name.c_str(), data.c_str());
}

std::string html5_resource::load_text_data(const std::string& name) const
{
    std::cout << "html5_resource::load_text_data " << name << std::endl;

    EM_ASM_ARGS({
        var name_str = Pointer_stringify($0);

        var buffer = "";
        var item = localStorage.getItem(name_str);
        if(item != null) {
            buffer = item;
        }

        FS.writeFile('buffer', buffer);
    }, name.c_str());

    std::ifstream t("buffer");
    std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

    return str;
}
<|endoftext|>


<commit_before>// Base header file.  Must be first.
#include <Include/PlatformDefinitions.hpp>

#include <cassert>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#else
#include <iostream>
#endif

#include <util/PlatformUtils.hpp>
#include <util/Mutexes.hpp>

#include <Include/XalanAutoPtr.hpp>

#include <XalanTransformer/XalanTransformer.hpp>

#if defined(WIN32)
//This is here for the threads.
#include <process.h>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(XALAN_POSIX2_AVAILABLE)
#include <pthread.h>
#include <unistd.h>
#else
#error Unsupported platform!
#endif

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::endl;
#endif

// This is here for memory leak testing.
#if defined(_DEBUG)
#include <crtdbg.h>
#endif

class SynchronizedCounter
{
public:

	SynchronizedCounter();

	~SynchronizedCounter();

	void
	increment();

	void
	decrement();

	unsigned long
	getCounter() const;

private:

	mutable XMLMutex	m_mutex;

	unsigned long		m_counter;
};

SynchronizedCounter::SynchronizedCounter() :
	m_mutex(),
	m_counter(0)
{
}

SynchronizedCounter::~SynchronizedCounter()
{
}

void
SynchronizedCounter::increment()
{
	XMLMutexLock	theLock(&m_mutex);

	if (m_counter < ULONG_MAX)
	{
		++m_counter;
	}
}

void
SynchronizedCounter::decrement()
{
	XMLMutexLock	theLock(&m_mutex);

	if (m_counter > 0)
	{
		--m_counter;
	}
}

unsigned long
SynchronizedCounter::getCounter() const
{
	return m_counter;
}

struct
ThreadInfo
{
	ThreadInfo(
			unsigned int			theThreadNumber = 0,
			SynchronizedCounter*	theCounter = 0) :
		m_threadNumber(theThreadNumber),
		m_counter(theCounter)
	{
	}

	unsigned int			m_threadNumber;

	SynchronizedCounter*	m_counter;
};

// Used to hold compiled stylesheet and pre-parsed source...
const XalanCompiledStylesheet*	glbCompiledStylesheet = 0;
const XalanParsedSource*		glbParsedSource = 0;

#if defined(WIN32)

extern "C" void theThreadRoutine(void* param);

void
#elif defined(XALAN_POSIX2_AVAILABLE)

extern "C" void* theThreadRoutine(void* param);

void*
#else
#error Unsupported platform!
#endif
theThreadRoutine(void*		param)
{
// This routine uses compiled stylesheet (glbStylesheetRoot), which is set using the
// theProcessor.setStylesheetRoot method. The transform is done using the theProcessor's
// process() method.

#if defined(XALAN_OLD_STYLE_CASTS)
	const ThreadInfo* const		theInfo = (const ThreadInfo*)param;
#else
	const ThreadInfo* const		theInfo = reinterpret_cast<const ThreadInfo*>(param);
#endif

	assert(theInfo != 0);

	theInfo->m_counter->increment();

	try
	{
		// Our input file.  The assumption is that the executable will be run
		// from same directory as the input files.

		// Generate the output file name.
		const XalanDOMString	theOutputFile(
				XalanDOMString("birds") +
				UnsignedLongToDOMString(theInfo->m_threadNumber) +
				XalanDOMString(".out"));

		// Create a transformer...
		XalanTransformer	theTransformer;

		// Do the transform...
		theTransformer.transform(*glbParsedSource, glbCompiledStylesheet, XSLTResultTarget(theOutputFile));
	}
	catch(...)
	{
		cerr << "Exception caught in thread " << theInfo->m_threadNumber;
	}

	// Decrement the counter because we're done...
	theInfo->m_counter->decrement();

#if defined(XALAN_POSIX2_AVAILABLE)
	return 0;
#endif
}

inline void
doSleep(unsigned int	theMilliseconds)
{
#if defined(WIN32)
	Sleep(theMilliseconds);
#elif defined(XALAN_POSIX2_AVAILABLE)
	usleep(theMilliseconds * 10);
#else
#error Unsupported platform!
#endif
}

void
doThreads(long	theThreadCount)
{
	cout << endl << "Starting " << theThreadCount << " threads." << endl;

	XalanArrayAutoPtr<ThreadInfo>	theThreadInfo(new ThreadInfo[theThreadCount]);

	try
	{
		cout << endl << "Clock before starting threads: " << clock() << endl;

		SynchronizedCounter		theCounter;

		long	i = 0;

		while (i < theThreadCount)
		{
			theThreadInfo[i].m_threadNumber = i;
			theThreadInfo[i].m_counter = &theCounter;

#if defined(WIN32)

			const unsigned long		theThreadID =
					_beginthread(theThreadRoutine, 4096, reinterpret_cast<LPVOID>(&theThreadInfo[i]));

			if (theThreadID == unsigned(-1))
			{
				cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
			}

#elif defined(XALAN_POSIX2_AVAILABLE)

			pthread_t	theThread;

			const int	theResult = pthread_create(&theThread, 0, theThreadRoutine, (void*)&theThreadInfo[i]);

			if (theResult != 0)
			{
				cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
			}
			else
			{
#if defined(OS390)
				pthread_detach(&theThread);
#else
				pthread_detach(theThread);
#endif
			}
#else
#error Unsupported platform!
#endif

			++i;
		}

		clock_t		theClock = 0;

		if (i == 0)
		{
			cerr << endl << "No threads were created!" << endl;
		}
		else
		{
			unsigned int	theCheckCount = 0;

			do
			{
				doSleep(2000);

				// Check a couple of times, just in case, since
				// getCounter() is not synchronized...
				if (theCounter.getCounter() == 0)
				{
					if (theCheckCount == 0)
					{
						theClock = clock();
					}

					++theCheckCount;
				}
			}
			while(theCheckCount < 2);
		}

		cout << endl << "Clock after threads: " << theClock << endl;
	}
	catch(...)
	{
		cerr << "Exception caught!!!"
			 << endl
			<< endl;
	}
}

int
main(
			int				argc,
			const char*		argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	if (argc > 2)
	{
		cerr << "Usage: ThreadTest"
			 << endl
			 << endl;
	}
	else
	{
		int		threadCount = 60;

		if (argc == 2)
		{
			threadCount = atoi(argv[1]);
		}

		try
		{
			// Initialize Xerces...
			XMLPlatformUtils::Initialize();

			// Initialize Xalan...
			XalanTransformer::initialize();

			{
				// Create a XalanTransformer.  We won't actually use this to transform --
				// it's just acting likely a factory for the compiled stylesheet and
				// pre-parsed source.
				XalanTransformer	theXalanTransformer;

				const char* const	theXSLFileName = "birds.xsl";

				theXalanTransformer.compileStylesheet(theXSLFileName, glbCompiledStylesheet);
				assert(glbCompiledStylesheet != 0);

				// Compile the XML source document as well. All threads will use
				// this binary representation of the source tree.
				const char* const	theXMLFileName = "birds.xml";

				theXalanTransformer.parseSource(theXMLFileName, glbParsedSource);
				assert(glbParsedSource != 0);

				doThreads(threadCount);
			}

			// Terminate Xalan...
			XalanTransformer::terminate();

			// Terminate Xerces...
			XMLPlatformUtils::Terminate();
		}
		catch(...)
		{
			cerr << "Exception caught!!!"
				 << endl
				 << endl;
		}

	}

	return 0;
}
<commit_msg>Fixed include file problem.<commit_after>// Base header file.  Must be first.
#include <Include/PlatformDefinitions.hpp>

#include <cassert>
#include <ctime>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#else
#include <iostream>
#endif

#include <util/PlatformUtils.hpp>
#include <util/Mutexes.hpp>

#include <Include/XalanAutoPtr.hpp>

#include <XalanTransformer/XalanTransformer.hpp>

#if defined(WIN32)
//This is here for the threads.
#include <process.h>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(XALAN_POSIX2_AVAILABLE)
#include <pthread.h>
#include <unistd.h>
#else
#error Unsupported platform!
#endif

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::endl;
#endif

// This is here for memory leak testing.
#if defined(_DEBUG)
#include <crtdbg.h>
#endif

class SynchronizedCounter
{
public:

	SynchronizedCounter();

	~SynchronizedCounter();

	void
	increment();

	void
	decrement();

	unsigned long
	getCounter() const;

private:

	mutable XMLMutex	m_mutex;

	unsigned long		m_counter;
};

SynchronizedCounter::SynchronizedCounter() :
	m_mutex(),
	m_counter(0)
{
}

SynchronizedCounter::~SynchronizedCounter()
{
}

void
SynchronizedCounter::increment()
{
	XMLMutexLock	theLock(&m_mutex);

	if (m_counter < ULONG_MAX)
	{
		++m_counter;
	}
}

void
SynchronizedCounter::decrement()
{
	XMLMutexLock	theLock(&m_mutex);

	if (m_counter > 0)
	{
		--m_counter;
	}
}

unsigned long
SynchronizedCounter::getCounter() const
{
	return m_counter;
}

struct
ThreadInfo
{
	ThreadInfo(
			unsigned int			theThreadNumber = 0,
			SynchronizedCounter*	theCounter = 0) :
		m_threadNumber(theThreadNumber),
		m_counter(theCounter)
	{
	}

	unsigned int			m_threadNumber;

	SynchronizedCounter*	m_counter;
};

// Used to hold compiled stylesheet and pre-parsed source...
const XalanCompiledStylesheet*	glbCompiledStylesheet = 0;
const XalanParsedSource*		glbParsedSource = 0;

#if defined(WIN32)

extern "C" void theThreadRoutine(void* param);

void
#elif defined(XALAN_POSIX2_AVAILABLE)

extern "C" void* theThreadRoutine(void* param);

void*
#else
#error Unsupported platform!
#endif
theThreadRoutine(void*		param)
{
// This routine uses compiled stylesheet (glbStylesheetRoot), which is set using the
// theProcessor.setStylesheetRoot method. The transform is done using the theProcessor's
// process() method.

#if defined(XALAN_OLD_STYLE_CASTS)
	const ThreadInfo* const		theInfo = (const ThreadInfo*)param;
#else
	const ThreadInfo* const		theInfo = reinterpret_cast<const ThreadInfo*>(param);
#endif

	assert(theInfo != 0);

	theInfo->m_counter->increment();

	try
	{
		// Our input file.  The assumption is that the executable will be run
		// from same directory as the input files.

		// Generate the output file name.
		const XalanDOMString	theOutputFile(
				XalanDOMString("birds") +
				UnsignedLongToDOMString(theInfo->m_threadNumber) +
				XalanDOMString(".out"));

		// Create a transformer...
		XalanTransformer	theTransformer;

		// Do the transform...
		theTransformer.transform(*glbParsedSource, glbCompiledStylesheet, XSLTResultTarget(theOutputFile));
	}
	catch(...)
	{
		cerr << "Exception caught in thread " << theInfo->m_threadNumber;
	}

	// Decrement the counter because we're done...
	theInfo->m_counter->decrement();

#if defined(XALAN_POSIX2_AVAILABLE)
	return 0;
#endif
}

inline void
doSleep(unsigned int	theMilliseconds)
{
#if defined(WIN32)
	Sleep(theMilliseconds);
#elif defined(XALAN_POSIX2_AVAILABLE)
	usleep(theMilliseconds * 10);
#else
#error Unsupported platform!
#endif
}

void
doThreads(long	theThreadCount)
{
	cout << endl << "Starting " << theThreadCount << " threads." << endl;

	XalanArrayAutoPtr<ThreadInfo>	theThreadInfo(new ThreadInfo[theThreadCount]);

	try
	{
		cout << endl << "Clock before starting threads: " << clock() << endl;

		SynchronizedCounter		theCounter;

		long	i = 0;

		while (i < theThreadCount)
		{
			theThreadInfo[i].m_threadNumber = i;
			theThreadInfo[i].m_counter = &theCounter;

#if defined(WIN32)

			const unsigned long		theThreadID =
					_beginthread(theThreadRoutine, 4096, reinterpret_cast<LPVOID>(&theThreadInfo[i]));

			if (theThreadID == unsigned(-1))
			{
				cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
			}

#elif defined(XALAN_POSIX2_AVAILABLE)

			pthread_t	theThread;

			const int	theResult = pthread_create(&theThread, 0, theThreadRoutine, (void*)&theThreadInfo[i]);

			if (theResult != 0)
			{
				cerr << endl << "Unable to create thread number " << i + 1 << "." << endl;
			}
			else
			{
#if defined(OS390)
				pthread_detach(&theThread);
#else
				pthread_detach(theThread);
#endif
			}
#else
#error Unsupported platform!
#endif

			++i;
		}

		clock_t		theClock = 0;

		if (i == 0)
		{
			cerr << endl << "No threads were created!" << endl;
		}
		else
		{
			unsigned int	theCheckCount = 0;

			do
			{
				doSleep(2000);

				// Check a couple of times, just in case, since
				// getCounter() is not synchronized...
				if (theCounter.getCounter() == 0)
				{
					if (theCheckCount == 0)
					{
						theClock = clock();
					}

					++theCheckCount;
				}
			}
			while(theCheckCount < 2);
		}

		cout << endl << "Clock after threads: " << theClock << endl;
	}
	catch(...)
	{
		cerr << "Exception caught!!!"
			 << endl
			<< endl;
	}
}

int
main(
			int				argc,
			const char*		argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	if (argc > 2)
	{
		cerr << "Usage: ThreadTest"
			 << endl
			 << endl;
	}
	else
	{
		int		threadCount = 60;

		if (argc == 2)
		{
			threadCount = atoi(argv[1]);
		}

		try
		{
			// Initialize Xerces...
			XMLPlatformUtils::Initialize();

			// Initialize Xalan...
			XalanTransformer::initialize();

			{
				// Create a XalanTransformer.  We won't actually use this to transform --
				// it's just acting likely a factory for the compiled stylesheet and
				// pre-parsed source.
				XalanTransformer	theXalanTransformer;

				const char* const	theXSLFileName = "birds.xsl";

				theXalanTransformer.compileStylesheet(theXSLFileName, glbCompiledStylesheet);
				assert(glbCompiledStylesheet != 0);

				// Compile the XML source document as well. All threads will use
				// this binary representation of the source tree.
				const char* const	theXMLFileName = "birds.xml";

				theXalanTransformer.parseSource(theXMLFileName, glbParsedSource);
				assert(glbParsedSource != 0);

				doThreads(threadCount);
			}

			// Terminate Xalan...
			XalanTransformer::terminate();

			// Terminate Xerces...
			XMLPlatformUtils::Terminate();
		}
		catch(...)
		{
			cerr << "Exception caught!!!"
				 << endl
				 << endl;
		}

	}

	return 0;
}
<|endoftext|>


<commit_before>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2021 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <gtest/gtest.h>
#include "math.hpp"
#include "ChebyshevDifferentiate.hpp"
#include "PoissonProblem.hpp"
#include "FastCosineTransform.hpp"

template<size_t N>
void sysslv(double a[N][N], double b[N])
{
    constexpr size_t n = N;
    double biga,save;
    int i,j,k,imax;

    for (j=0;j<n;j++) {
        biga=0.0;
        for(i=j;i<n;i++)
        if (std::fabs(biga) < std::fabs(a[i][j])) {
            biga=a[i][j];
            imax=i;
        }
        if (std::fabs(biga) == 0.0) {
            throw std::logic_error("Very singular matrix...");
        }
        for (k=j;k<n;k++) {
            save=a[imax][k];
            a[imax][k]=a[j][k];
            a[j][k]=save/biga;
        }
        save=b[imax];
        b[imax]=b[j];
        b[j]=save/biga;
        for (i=j+1;i<n;i++) {
            for(k=j+1;k<n;k++)
                a[i][k] -= a[i][j]*a[j][k];
            b[i] -= b[j]*a[i][j];
        }
    }
    for (k=n-2;k>=0;k--)
        for(j=n-1;j>k;j--)
            b[k] -= a[k][j]*b[j];
}

TEST(cftSuite, test_cosfft1)
{
    constexpr size_t M = 2;

    RowVectorXd x(M + 1), x_inv(M + 1);

    x     << 1.,  2., 3.;
    x_inv << 6., -2., 2.;

    FCT::cosfft1(M, x);

    EXPECT_DOUBLE_EQ((x - x_inv).norm(), 0.0);
}

TEST(cftSuite, test_cosfft12)
{
    constexpr size_t M = 32;
    auto y = [](double x) {return x*x*x*x - 1;}; /// \f$y = x^4 - 1\f$
    double x_min = -1., x_max = 1.;
    double xa = 0.5*(x_min-x_max);
    double xb = 0.5*(x_min+x_max);
    RowVectorXd x_grid(M + 1), f_vals1(M + 1), f_vals2(M + 1);
    for (size_t i = 0; i <= M; i++) {
        x_grid[i] = xa*std::cos(M_PI*i/(double)M)+xb;
    }

    for (size_t i = 0; i <= M; i++) {
        f_vals2[i] = f_vals1[i] = y(x_grid[i]);
    }

    FCT::cosfft1(M, f_vals1);
    FCT::cosfft1(M, f_vals1, FCT::TransformType::Inverse);

    // EXPECT_DOUBLE_EQ((f_vals1 - f_vals2).norm(), 0.0);
    constexpr double EPS = 1e-14;
    EXPECT_NEAR((f_vals1 - f_vals2).norm(), 0.0, EPS);
}

/// check that `.transpose()` and `.transposeInPlace()`
/// surely work with non-square matrices
TEST(eigenSuite, test_transpose)
{
    constexpr size_t M = 2;
    constexpr size_t N = 3;
    RowMatrixXd ma(M, N), maT;
    ma << 1., 2., 3.,
          4., 5., 6.;
    maT = ma.transpose();

    // std::cout << ma << std::endl;
    // std::cout << maT << std::endl;

    EXPECT_EQ(ma.rows(), maT.cols());
    EXPECT_EQ(maT.rows(), ma.cols());

    ma.transposeInPlace();

    EXPECT_EQ(ma.rows(), maT.rows());
    EXPECT_EQ(ma.cols(), maT.cols());

    // assertion failure if use
    // `Eigen::Ref<RowMatrixXd>` instead of plain `RowMatrixXd&`
    auto transpose = [](RowMatrixXd& ma) {
        ma.transposeInPlace();
    };

    transpose(ma);

    EXPECT_EQ(ma.rows(), maT.cols());
    EXPECT_EQ(maT.rows(), ma.cols());
}

TEST(eigenSuite, test_unity)
{
    constexpr size_t M = 2;
    constexpr size_t N = 3;
    RowMatrixXd ma;

    ma = Eigen::MatrixXd::Identity(M + 1, N + 1);

    std::cout << "ma:\n" << ma << std::endl;

}

TEST(cftSuite, test_cf2)
{
    constexpr size_t M = 2;
    constexpr size_t N = 4;

    RowMatrixXd m(M + 1, N + 1), m_inv(M + 1, N + 1), m1;

    m << 1., 2., 3., 1., 2.,
         4., 5., 6., 4., 5.,
         7., 8., 9., 7., 8.;
    m_inv <<  72.,    -0.87867965644035673,   9.,     -5.1213203435596428,  18.,
             -30., -4.4408920985006262e-16,  -6.,  4.4408920985006262e-16,  -6.,
              24.,    -0.29289321881345254,   3.,     -1.7071067811865479,   6.;

    m1 = m;

    FCT::cft2(M, N, m);
    FCT::cft2_with_transpose(M, N, m1);

    // std::cout << std::setprecision(17) << m << std::endl;

    constexpr double EPS = 1e-14;
    EXPECT_NEAR((m - m_inv).norm(), 0.0, EPS);
    EXPECT_NEAR((m - m1).norm(), 0.0, EPS);
}

TEST(bsSuite, test_gauss_elim)
{
    constexpr double EPS = 1e-12;

    constexpr size_t M = 4;

    // https://mxncalc.com/gaussian-elimination-calculator
    double A[M][M] = {{1.,  2., 3.,  4.},
                      {5.,  6., 8.,  5.},
                      {4., 15., 2., 12.},
                      {3.,  2., 5.,  6.},};
    double b[M] = {11., 12., 3., 7.,};
    double x[M] = { -7.127'853'881'278'5,
                     1.237'442'922'374'4,
                     4.858'447'488'584'5,
                     0.269'406'392'694'06,
                  };
    Eigen::Vector4d bb(b), xx(x);
    Eigen::Matrix4d AA(reinterpret_cast<double*>(A));
    AA.transposeInPlace();
    // std::cout << "AA: " << AA << std::endl;
    sysslv(A, b);
    Eigen::Vector4d b2(b);

    //EXPECT_DOUBLE_EQ((b2 - xx).norm(), 0.0);
    // Expected equality of these values:
    //   (b2 - xx).norm()
    //     Which is: 5.3413613165043815e-14
    //   0.0
    //     Which is: 0
    EXPECT_NEAR((b2 - xx).norm(), 0.0, EPS);

    Eigen::Vector4d x2 = AA.lu().solve(bb);
    // std::cout << "x2: " << x2 << std::endl;
    // std::cout << "xx: " << xx << std::endl;
    EXPECT_NEAR((x2 - xx).norm(), 0.0, EPS);
}

TEST(ChebyshevDifferentiate, test_deriv1)
{
    constexpr size_t M = 32;

    auto y        = [](double x) {return x*x*x*x + sin(x);}; /// \f$y = x^4 + \sin x\f$
    auto y_deriv1 = [](double x) {return 4*x*x*x + cos(x);}; /// \f$y = 4x^3 + \cos x\f$

    RowVectorXd x_grid(M + 1), f_vals(M + 1), f_deriv_vals(M + 1);

    double x_min = -1., x_max = 1.;
    double xa = 0.5*(x_max-x_min);
    double xb = 0.5*(x_min+x_max);

    // std::cout << "xa: " << xa << " xb: " << xb << std::endl;

    for (size_t i = 0; i <= M; i++) {
        x_grid[i] = xa*std::cos(M_PI*i/(double)M)+xb;
    }

    // std::cout << "x_grid: " << x_grid << std::endl;

    for (size_t i = 0; i <= M; i++) {
        f_vals[i]       = y        (x_grid[i]);
        f_deriv_vals[i] = y_deriv1 (x_grid[i]);
    }

    // std::cout << "f_vals: [" << f_vals << "]\n";
    // std::cout << "f_deriv_vals: [" << f_deriv_vals << "]\n";

    FCT::cosfft1(M, f_vals, FCT::TransformType::Inverse);
    CS::spectral_differentiate(M, f_vals, f_vals, 2.0 / (x_max - x_min));
    FCT::cosfft1(M, f_vals);

    // std::cout << "f_vals: [" << f_vals << "]\n";
    // std::cout << "f_vals - f_deriv_vals: [" << f_vals - f_deriv_vals << "]\n";

    //EXPECT_DOUBLE_EQ((f_vals - f_deriv_vals).norm(), 0.0);

    constexpr double EPS = 1e-10;
    EXPECT_NEAR((f_vals - f_deriv_vals).norm(), 0.0, EPS);
}

TEST(PoissonProblem, test_homogeneous_boundary)
{
    constexpr size_t M = 4;

    double A[M + 1][M + 1] = { {1.,  2., 3.,  4.,  8.,},
                               {5.,  6., 8.,  5.,  7.,},
                               {3.,  5., 7.,  2.,  1.,},
                               {4., 15., 2., 12., 11.,},
                               {3.,  2., 5.,  6.,  5.,}, };

    RowMatrixXd AA(M + 1, M + 1), BB = RowMatrixXd::Zero(M + 1, M + 1);

    for (size_t i = 0; i <= M; ++i) {
        for (size_t j = 0; j <= M; ++j) {
            AA(i, j) = A[i][j];
        }
    }

    // std::cout << "AA: [\n" << AA << "]\n";
    CS::homogeneous_boundary(M, M, AA, BB);
    // std::cout << "BB: [\n" << BB << "]\n";
    // std::cout << "AA: [\n" << AA << "]\n";
    CS::homogeneous_boundary(M, M, AA, AA);
    // std::cout << "AA: [\n" << AA << "]\n";
    EXPECT_DOUBLE_EQ((AA - BB).norm(), 0.0);
}
<commit_msg>fixed `test_unity` test<commit_after>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2021 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <gtest/gtest.h>
#include "math.hpp"
#include "ChebyshevDifferentiate.hpp"
#include "PoissonProblem.hpp"
#include "FastCosineTransform.hpp"

template<size_t N>
void sysslv(double a[N][N], double b[N])
{
    constexpr size_t n = N;
    double biga,save;
    int i,j,k,imax;

    for (j=0;j<n;j++) {
        biga=0.0;
        for(i=j;i<n;i++)
        if (std::fabs(biga) < std::fabs(a[i][j])) {
            biga=a[i][j];
            imax=i;
        }
        if (std::fabs(biga) == 0.0) {
            throw std::logic_error("Very singular matrix...");
        }
        for (k=j;k<n;k++) {
            save=a[imax][k];
            a[imax][k]=a[j][k];
            a[j][k]=save/biga;
        }
        save=b[imax];
        b[imax]=b[j];
        b[j]=save/biga;
        for (i=j+1;i<n;i++) {
            for(k=j+1;k<n;k++)
                a[i][k] -= a[i][j]*a[j][k];
            b[i] -= b[j]*a[i][j];
        }
    }
    for (k=n-2;k>=0;k--)
        for(j=n-1;j>k;j--)
            b[k] -= a[k][j]*b[j];
}

TEST(cftSuite, test_cosfft1)
{
    constexpr size_t M = 2;

    RowVectorXd x(M + 1), x_inv(M + 1);

    x     << 1.,  2., 3.;
    x_inv << 6., -2., 2.;

    FCT::cosfft1(M, x);

    EXPECT_DOUBLE_EQ((x - x_inv).norm(), 0.0);
}

TEST(cftSuite, test_cosfft12)
{
    constexpr size_t M = 32;
    auto y = [](double x) {return x*x*x*x - 1;}; /// \f$y = x^4 - 1\f$
    double x_min = -1., x_max = 1.;
    double xa = 0.5*(x_min-x_max);
    double xb = 0.5*(x_min+x_max);
    RowVectorXd x_grid(M + 1), f_vals1(M + 1), f_vals2(M + 1);
    for (size_t i = 0; i <= M; i++) {
        x_grid[i] = xa*std::cos(M_PI*i/(double)M)+xb;
    }

    for (size_t i = 0; i <= M; i++) {
        f_vals2[i] = f_vals1[i] = y(x_grid[i]);
    }

    FCT::cosfft1(M, f_vals1);
    FCT::cosfft1(M, f_vals1, FCT::TransformType::Inverse);

    // EXPECT_DOUBLE_EQ((f_vals1 - f_vals2).norm(), 0.0);
    constexpr double EPS = 1e-14;
    EXPECT_NEAR((f_vals1 - f_vals2).norm(), 0.0, EPS);
}

/// check that `.transpose()` and `.transposeInPlace()`
/// surely work with non-square matrices
TEST(eigenSuite, test_transpose)
{
    constexpr size_t M = 2;
    constexpr size_t N = 3;
    RowMatrixXd ma(M, N), maT;
    ma << 1., 2., 3.,
          4., 5., 6.;
    maT = ma.transpose();

    // std::cout << ma << std::endl;
    // std::cout << maT << std::endl;

    EXPECT_EQ(ma.rows(), maT.cols());
    EXPECT_EQ(maT.rows(), ma.cols());

    ma.transposeInPlace();

    EXPECT_EQ(ma.rows(), maT.rows());
    EXPECT_EQ(ma.cols(), maT.cols());

    // assertion failure if use
    // `Eigen::Ref<RowMatrixXd>` instead of plain `RowMatrixXd&`
    auto transpose = [](RowMatrixXd& ma) {
        ma.transposeInPlace();
    };

    transpose(ma);

    EXPECT_EQ(ma.rows(), maT.cols());
    EXPECT_EQ(maT.rows(), ma.cols());
}

TEST(eigenSuite, test_unity)
{
    constexpr size_t M = 2;
    constexpr size_t N = 3;
    RowMatrixXd ma;

    ma = Eigen::MatrixXd::Identity(M + 1, N + 1);

    // std::cout << "ma:\n" << ma << std::endl;

    EXPECT_EQ(ma.rows(), M + 1);
    EXPECT_EQ(ma.cols(), N + 1);

    ma.transposeInPlace();

    EXPECT_EQ(ma.rows(), N + 1);
    EXPECT_EQ(ma.cols(), M + 1);

    EXPECT_EQ(ma(0, 0), 1.0);
    EXPECT_EQ(ma(1, 1), 1.0);
    EXPECT_EQ(ma(2, 2), 1.0);
    EXPECT_EQ(ma(1, 2), 0.0);
    EXPECT_EQ(ma(2, 1), 0.0);
}

TEST(cftSuite, test_cf2)
{
    constexpr size_t M = 2;
    constexpr size_t N = 4;

    RowMatrixXd m(M + 1, N + 1), m_inv(M + 1, N + 1), m1;

    m << 1., 2., 3., 1., 2.,
         4., 5., 6., 4., 5.,
         7., 8., 9., 7., 8.;
    m_inv <<  72.,    -0.87867965644035673,   9.,     -5.1213203435596428,  18.,
             -30., -4.4408920985006262e-16,  -6.,  4.4408920985006262e-16,  -6.,
              24.,    -0.29289321881345254,   3.,     -1.7071067811865479,   6.;

    m1 = m;

    FCT::cft2(M, N, m);
    FCT::cft2_with_transpose(M, N, m1);

    // std::cout << std::setprecision(17) << m << std::endl;

    constexpr double EPS = 1e-14;
    EXPECT_NEAR((m - m_inv).norm(), 0.0, EPS);
    EXPECT_NEAR((m - m1).norm(), 0.0, EPS);
}

TEST(bsSuite, test_gauss_elim)
{
    constexpr double EPS = 1e-12;

    constexpr size_t M = 4;

    // https://mxncalc.com/gaussian-elimination-calculator
    double A[M][M] = {{1.,  2., 3.,  4.},
                      {5.,  6., 8.,  5.},
                      {4., 15., 2., 12.},
                      {3.,  2., 5.,  6.},};
    double b[M] = {11., 12., 3., 7.,};
    double x[M] = { -7.127'853'881'278'5,
                     1.237'442'922'374'4,
                     4.858'447'488'584'5,
                     0.269'406'392'694'06,
                  };
    Eigen::Vector4d bb(b), xx(x);
    Eigen::Matrix4d AA(reinterpret_cast<double*>(A));
    AA.transposeInPlace();
    // std::cout << "AA: " << AA << std::endl;
    sysslv(A, b);
    Eigen::Vector4d b2(b);

    //EXPECT_DOUBLE_EQ((b2 - xx).norm(), 0.0);
    // Expected equality of these values:
    //   (b2 - xx).norm()
    //     Which is: 5.3413613165043815e-14
    //   0.0
    //     Which is: 0
    EXPECT_NEAR((b2 - xx).norm(), 0.0, EPS);

    Eigen::Vector4d x2 = AA.lu().solve(bb);
    // std::cout << "x2: " << x2 << std::endl;
    // std::cout << "xx: " << xx << std::endl;
    EXPECT_NEAR((x2 - xx).norm(), 0.0, EPS);
}

TEST(ChebyshevDifferentiate, test_deriv1)
{
    constexpr size_t M = 32;

    auto y        = [](double x) {return x*x*x*x + sin(x);}; /// \f$y = x^4 + \sin x\f$
    auto y_deriv1 = [](double x) {return 4*x*x*x + cos(x);}; /// \f$y = 4x^3 + \cos x\f$

    RowVectorXd x_grid(M + 1), f_vals(M + 1), f_deriv_vals(M + 1);

    double x_min = -1., x_max = 1.;
    double xa = 0.5*(x_max-x_min);
    double xb = 0.5*(x_min+x_max);

    // std::cout << "xa: " << xa << " xb: " << xb << std::endl;

    for (size_t i = 0; i <= M; i++) {
        x_grid[i] = xa*std::cos(M_PI*i/(double)M)+xb;
    }

    // std::cout << "x_grid: " << x_grid << std::endl;

    for (size_t i = 0; i <= M; i++) {
        f_vals[i]       = y        (x_grid[i]);
        f_deriv_vals[i] = y_deriv1 (x_grid[i]);
    }

    // std::cout << "f_vals: [" << f_vals << "]\n";
    // std::cout << "f_deriv_vals: [" << f_deriv_vals << "]\n";

    FCT::cosfft1(M, f_vals, FCT::TransformType::Inverse);
    CS::spectral_differentiate(M, f_vals, f_vals, 2.0 / (x_max - x_min));
    FCT::cosfft1(M, f_vals);

    // std::cout << "f_vals: [" << f_vals << "]\n";
    // std::cout << "f_vals - f_deriv_vals: [" << f_vals - f_deriv_vals << "]\n";

    //EXPECT_DOUBLE_EQ((f_vals - f_deriv_vals).norm(), 0.0);

    constexpr double EPS = 1e-10;
    EXPECT_NEAR((f_vals - f_deriv_vals).norm(), 0.0, EPS);
}

TEST(PoissonProblem, test_homogeneous_boundary)
{
    constexpr size_t M = 4;

    double A[M + 1][M + 1] = { {1.,  2., 3.,  4.,  8.,},
                               {5.,  6., 8.,  5.,  7.,},
                               {3.,  5., 7.,  2.,  1.,},
                               {4., 15., 2., 12., 11.,},
                               {3.,  2., 5.,  6.,  5.,}, };

    RowMatrixXd AA(M + 1, M + 1), BB = RowMatrixXd::Zero(M + 1, M + 1);

    for (size_t i = 0; i <= M; ++i) {
        for (size_t j = 0; j <= M; ++j) {
            AA(i, j) = A[i][j];
        }
    }

    // std::cout << "AA: [\n" << AA << "]\n";
    CS::homogeneous_boundary(M, M, AA, BB);
    // std::cout << "BB: [\n" << BB << "]\n";
    // std::cout << "AA: [\n" << AA << "]\n";
    CS::homogeneous_boundary(M, M, AA, AA);
    // std::cout << "AA: [\n" << AA << "]\n";
    EXPECT_DOUBLE_EQ((AA - BB).norm(), 0.0);
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <unistd.h>
#ifdef __MACH__
#include <stdlib.h>
#include <stddef.h>
#include <gsl/gsl_assert>
void* memalign(size_t alignment, size_t size) {
  void* ptr {nullptr};
  int res = posix_memalign(&ptr, alignment, size);
  Ensures(res == 0);
  return ptr;
}
void* aligned_alloc(size_t alignment, size_t size) {
  return memalign(alignment, size);
}
#endif

char _DISK_START_;
char _DISK_END_;

#include <util/statman.hpp>
Statman& Statman::get() {
  static uintptr_t start {0};
  static const size_t memsize = 0x1000000;
  if (!start) {
    start = (uintptr_t) malloc(memsize);
  }
  static Statman statman_{start, memsize / sizeof(Stat)};
  return statman_;
}

/// RTC ///
#include <rtc>
RTC::timestamp_t RTC::booted_at = 0;
void RTC::init() {}

#include <service>
const char* service_binary_name__ = "Service binary name";
const char* service_name__        = "Service name";

void Service::ready()
{
  printf("Service::ready() called\n");
}

extern "C"
void kprintf(char* format, ...)
{
  va_list args;
  va_start(args, format);
  vprintf(format, args);
  va_end(args);
}

extern "C"
void kprint(char* str)
{
printf("%s", str);
}

#include <kernel/os.hpp>
void OS::start(unsigned, unsigned) {}
void OS::default_stdout(const char*, size_t) {}
void OS::event_loop() {}
void OS::block() {}
void OS::halt() {}
void OS::resume_softreset(intptr_t) {}
bool OS::is_softreset_magic(uint32_t) {
  return true;
}

void __x86_init_paging(void*){};
namespace x86 {
namespace paging {
  void invalidate(void* pageaddr){};
}}

__attribute__((constructor))
void paging_test_init(){
  extern uintptr_t __exec_begin;
  extern uintptr_t __exec_end;
  __exec_begin = 0xa00000;
  __exec_end = 0xb0000b;
}

void OS::multiboot(unsigned) {}

#include <system_log>
void SystemLog::initialize() {}
void SystemLog::set_flags(uint32_t) {}

/// Kernel ///
char _binary_apic_boot_bin_end;
char _binary_apic_boot_bin_start;
char __plugin_ctors_start;
char __plugin_ctors_end;
char __service_ctors_start;
char __service_ctors_end;

char _ELF_START_;
char _ELF_END_;
uintptr_t _MULTIBOOT_START_;
uintptr_t _LOAD_START_;
uintptr_t _LOAD_END_;
uintptr_t _BSS_END_;
uintptr_t _TEXT_START_;
uintptr_t _TEXT_END_;
uintptr_t _EXEC_END_;

extern "C" {
  uintptr_t get_cpu_esp() {
    return 0xdeadbeef;
  }

/// C ABI ///
  void _init_c_runtime() {}
  void _init_bss() {}

#ifdef __MACH__
  void _init() {}
#endif

  void __libc_init_array () {}

  uintptr_t _multiboot_free_begin(uintptr_t) {
    return 0;
  }
  uintptr_t _move_symbols(uintptr_t) {
    return 0;
  }

  /// malloc ///
  struct mallinfo { int x; };
  struct mallinfo mallinfo() {
    return {0};
  }
  void malloc_trim() {}
  uintptr_t heap_end = std::numeric_limits<uintptr_t>::max();

  void __init_serial1 () {}

  void __serial_print1(const char* cstr) {
    printf("<serial print1> %s\n", cstr);
  }

  void __serial_print(const char* cstr, int len) {
    printf("<serial print> %.*s", len, cstr);
  }
} // ~ extern "C"

/// platform ///
void* __multiboot_addr;

void __platform_init() {}
extern "C" void __init_sanity_checks() {}
extern "C" void kernel_sanity_checks() {}

/// arch ///
void __arch_poweroff() {}
void __arch_reboot() {}
void __arch_subscribe_irq(uint8_t) {}
void __arch_enable_legacy_irq(uint8_t) {}
void __arch_disable_legacy_irq(uint8_t) {}

delegate<uint64_t()> systime_override = [] () -> uint64_t { return 0; };
uint64_t __arch_system_time() noexcept {
  return systime_override();
}
#include <sys/time.h>
timespec __arch_wall_clock() noexcept {
  return timespec{0, 0};
}

/// smp ///
#include <smp>
int SMP::cpu_id() noexcept {
  return 0;
}
void SMP::global_lock() noexcept {}
void SMP::global_unlock() noexcept {}
void SMP::add_task(SMP::task_func func, int) { func(); }
void SMP::signal(int) {}

extern "C"
void (*current_eoi_mechanism) () = nullptr;

#ifdef ARCH_X86
#include "../../src/arch/x86/apic.hpp"
namespace x86 {
  IApic& APIC::get() noexcept { return *(IApic*) 0; }
}
#endif

#ifndef ARCH_X86
bool rdrand32(uint32_t* result) {
  *result = rand();
  return true;
}

/// heap ///
uintptr_t __brk_max = 0;
uintptr_t OS::heap_begin() noexcept {
  return 0;
}
uintptr_t OS::heap_end() noexcept {
  return 1 << 30;
}
uintptr_t OS::heap_max() noexcept {
  return -1;
}

#endif
<commit_msg>test: add OS::heap_usage to os_mock<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <unistd.h>
#ifdef __MACH__
#include <stdlib.h>
#include <stddef.h>
#include <gsl/gsl_assert>
void* memalign(size_t alignment, size_t size) {
  void* ptr {nullptr};
  int res = posix_memalign(&ptr, alignment, size);
  Ensures(res == 0);
  return ptr;
}
void* aligned_alloc(size_t alignment, size_t size) {
  return memalign(alignment, size);
}
#endif

char _DISK_START_;
char _DISK_END_;

#include <util/statman.hpp>
Statman& Statman::get() {
  static uintptr_t start {0};
  static const size_t memsize = 0x1000000;
  if (!start) {
    start = (uintptr_t) malloc(memsize);
  }
  static Statman statman_{start, memsize / sizeof(Stat)};
  return statman_;
}

/// RTC ///
#include <rtc>
RTC::timestamp_t RTC::booted_at = 0;
void RTC::init() {}

#include <service>
const char* service_binary_name__ = "Service binary name";
const char* service_name__        = "Service name";

void Service::ready()
{
  printf("Service::ready() called\n");
}

extern "C"
void kprintf(char* format, ...)
{
  va_list args;
  va_start(args, format);
  vprintf(format, args);
  va_end(args);
}

extern "C"
void kprint(char* str)
{
printf("%s", str);
}

#include <kernel/os.hpp>
void OS::start(unsigned, unsigned) {}
void OS::default_stdout(const char*, size_t) {}
void OS::event_loop() {}
void OS::block() {}
void OS::halt() {}
void OS::resume_softreset(intptr_t) {}
bool OS::is_softreset_magic(uint32_t) {
  return true;
}

void __x86_init_paging(void*){};
namespace x86 {
namespace paging {
  void invalidate(void* pageaddr){};
}}

__attribute__((constructor))
void paging_test_init(){
  extern uintptr_t __exec_begin;
  extern uintptr_t __exec_end;
  __exec_begin = 0xa00000;
  __exec_end = 0xb0000b;
}

void OS::multiboot(unsigned) {}

#include <system_log>
void SystemLog::initialize() {}
void SystemLog::set_flags(uint32_t) {}

/// Kernel ///
char _binary_apic_boot_bin_end;
char _binary_apic_boot_bin_start;
char __plugin_ctors_start;
char __plugin_ctors_end;
char __service_ctors_start;
char __service_ctors_end;

char _ELF_START_;
char _ELF_END_;
uintptr_t _MULTIBOOT_START_;
uintptr_t _LOAD_START_;
uintptr_t _LOAD_END_;
uintptr_t _BSS_END_;
uintptr_t _TEXT_START_;
uintptr_t _TEXT_END_;
uintptr_t _EXEC_END_;

extern "C" {
  uintptr_t get_cpu_esp() {
    return 0xdeadbeef;
  }

/// C ABI ///
  void _init_c_runtime() {}
  void _init_bss() {}

#ifdef __MACH__
  void _init() {}
#endif

  void __libc_init_array () {}

  uintptr_t _multiboot_free_begin(uintptr_t) {
    return 0;
  }
  uintptr_t _move_symbols(uintptr_t) {
    return 0;
  }

  /// malloc ///
  struct mallinfo { int x; };
  struct mallinfo mallinfo() {
    return {0};
  }
  void malloc_trim() {}
  uintptr_t heap_end = std::numeric_limits<uintptr_t>::max();

  void __init_serial1 () {}

  void __serial_print1(const char* cstr) {
    printf("<serial print1> %s\n", cstr);
  }

  void __serial_print(const char* cstr, int len) {
    printf("<serial print> %.*s", len, cstr);
  }
} // ~ extern "C"

/// platform ///
void* __multiboot_addr;

void __platform_init() {}
extern "C" void __init_sanity_checks() {}
extern "C" void kernel_sanity_checks() {}

/// arch ///
void __arch_poweroff() {}
void __arch_reboot() {}
void __arch_subscribe_irq(uint8_t) {}
void __arch_enable_legacy_irq(uint8_t) {}
void __arch_disable_legacy_irq(uint8_t) {}

delegate<uint64_t()> systime_override = [] () -> uint64_t { return 0; };
uint64_t __arch_system_time() noexcept {
  return systime_override();
}
#include <sys/time.h>
timespec __arch_wall_clock() noexcept {
  return timespec{0, 0};
}

/// smp ///
#include <smp>
int SMP::cpu_id() noexcept {
  return 0;
}
void SMP::global_lock() noexcept {}
void SMP::global_unlock() noexcept {}
void SMP::add_task(SMP::task_func func, int) { func(); }
void SMP::signal(int) {}

extern "C"
void (*current_eoi_mechanism) () = nullptr;

#ifdef ARCH_X86
#include "../../src/arch/x86/apic.hpp"
namespace x86 {
  IApic& APIC::get() noexcept { return *(IApic*) 0; }
}
#endif

#ifndef ARCH_X86
bool rdrand32(uint32_t* result) {
  *result = rand();
  return true;
}

/// heap ///
uintptr_t __brk_max = 0;
uintptr_t OS::heap_begin() noexcept {
  return 0;
}
uintptr_t OS::heap_end() noexcept {
  return 1 << 30;
}

size_t OS::heap_usage() noexcept {
  return OS::heap_end();
}

uintptr_t OS::heap_max() noexcept {
  return -1;
}

#endif
<|endoftext|>