<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/component/collision/DefaultContactManager.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace collision
{

SOFA_DECL_CLASS(DefaultContactManager)

int DefaultContactManagerClass = core::RegisterObject("Default class to create reactions to the collisions")
        .add< DefaultContactManager >()
        .addAlias("CollisionResponse")
        ;

DefaultContactManager::DefaultContactManager()
    : response(initData(&response, "response", "contact response class"))
{
}

DefaultContactManager::~DefaultContactManager()
{
    // Contacts are now attached to the graph.
    // So they will be deleted by the DeleteVisitor
    // FIX crash on unload bug. -- J. Allard
    //clear();
}

sofa::helper::OptionsGroup DefaultContactManager::initializeResponseOptions(core::collision::Pipeline *pipeline)
{
    helper::set<std::string> listResponse;
    if (pipeline) listResponse=pipeline->getResponseList();
    else
    {
        core::collision::Contact::Factory::iterator it;
        for (it=core::collision::Contact::Factory::getInstance()->begin(); it!=core::collision::Contact::Factory::getInstance()->end(); ++it)
        {
            listResponse.insert(it->first);
        }
    }
    sofa::helper::OptionsGroup responseOptions(listResponse);
    if (listResponse.find("default") != listResponse.end())
        responseOptions.setSelectedItem("default");
    return responseOptions;
}

void DefaultContactManager::init()
{
    core::collision::Pipeline *pipeline=static_cast<simulation::Node*>(getContext())->collisionPipeline;
    response.setValue(initializeResponseOptions(pipeline));
}
void DefaultContactManager::cleanup()
{
    for (sofa::helper::vector<core::collision::Contact*>::iterator it=contacts.begin(); it!=contacts.end(); ++it)
    {
        (*it)->removeResponse();
        (*it)->cleanup();
        delete *it;
    }
    contacts.clear();
    contactMap.clear();
}

void DefaultContactManager::createContacts(DetectionOutputMap& outputsMap)
{
    //serr<<"DefaultContactManager::createContacts"<<sendl;

    //outputsMap.clear();
    //for (sofa::helper::vector<core::collision::DetectionOutput*>::const_iterator it = outputs.begin(); it!=outputs.end(); ++it)
    //{
    //	core::collision::DetectionOutput* o = *it;
    //	outputsMap[std::make_pair(o->elem.first.getCollisionModel(),o->elem.second.getCollisionModel())].push_back(o);
    //}

    // Remove any inactive contacts or add any new contact
    DetectionOutputMap::iterator outputsIt = outputsMap.begin();
    std::map< std::pair<core::CollisionModel*,core::CollisionModel*>, core::collision::Contact* >::iterator contactIt = contactMap.begin();
    int nbContact = 0;
    //static DetectionOutputVector emptyContacts;
    while (outputsIt!=outputsMap.end() || contactIt!=contactMap.end())
    {
        if (outputsIt!=outputsMap.end() && (contactIt == contactMap.end() || outputsIt->first < contactIt->first))
        {
            // new contact
            //sout << "Creation new "<<contacttype<<" contact"<<sendl;
            core::CollisionModel* model1 = outputsIt->first.first;
            core::CollisionModel* model2 = outputsIt->first.second;
            std::string responseUsed = getContactResponse(model1, model2);
            core::collision::Contact* contact = core::collision::Contact::Create(responseUsed, model1, model2, intersectionMethod);
            if (contact == NULL) serr << "Contact "<<responseUsed<<" between " << model1->getClassName()<<" and "<<model2->getClassName() << " creation failed"<<sendl;
            else
            {
                contactMap[std::make_pair(model1, model2)] = contact;
                contact->setName(model1->getName()+std::string("-")+model2->getName());
                contact->f_printLog.setValue(this->f_printLog.getValue());
                contact->init();
                contact->setDetectionOutputs(outputsIt->second);
                ++nbContact;
            }
            ++outputsIt;
        }
        else if (contactIt!=contactMap.end() && (outputsIt == outputsMap.end() || contactIt->first < outputsIt->first))
        {
            // inactive contact
            //sout << "Deleting inactive "<<contacttype<<" contact"<<sendl;
            if (contactIt->second->keepAlive())
            {
                contactIt->second->setDetectionOutputs(NULL);
                ++nbContact;
                ++contactIt;
            }
            else
            {
                std::map< std::pair<core::CollisionModel*,core::CollisionModel*>, core::collision::Contact* >::iterator contactIt2 = contactIt;
                ++contactIt2;
                contactIt->second->removeResponse();
                contactIt->second->cleanup();
                delete contactIt->second;
                contactMap.erase(contactIt);
                contactIt = contactIt2;
            }
        }
        else
        {
            // corresponding contact and outputs
            contactIt->second->setDetectionOutputs(outputsIt->second);
            ++nbContact;
            ++outputsIt;
            ++contactIt;
        }
    }
    // now update contactVec
    contacts.clear();
    contacts.reserve(nbContact);
    contactIt = contactMap.begin();
    while (contactIt!=contactMap.end())
    {
        contacts.push_back(contactIt->second);
        ++contactIt;
    }
    // compute number of contacts attached to each collision model
    std::map<core::CollisionModel*,int> nbContactsMap;
    for (unsigned int i=0; i<contacts.size(); ++i)
    {
        std::pair< core::CollisionModel*, core::CollisionModel* > cms = contacts[i]->getCollisionModels();
        nbContactsMap[cms.first]++;
        if (cms.second != cms.first)
            nbContactsMap[cms.second]++;
    }
    sofa::helper::vector<core::CollisionModel*> collisionModels;
    simulation::Node* context = dynamic_cast<simulation::Node*>(getContext());
    context->getTreeObjects<core::CollisionModel>(&collisionModels);
    for (unsigned int i=0; i<collisionModels.size(); ++i)
    {
        collisionModels[i]->setNumberOfContacts(nbContactsMap[collisionModels[i]]);
    }
}

std::string DefaultContactManager::getContactResponse(core::CollisionModel* model1, core::CollisionModel* model2)
{
    std::string responseUsed = response.getValue().getSelectedItem();
    std::string response1 = model1->getContactResponse();
    std::string response2 = model2->getContactResponse();

    if (response1.empty()  &&  response2.empty()) return responseUsed;
    if (response1.empty()  && !response2.empty()) return response2;
    if (!response1.empty() &&  response2.empty()) return response1;

    if (response1 != response2) return responseUsed;
    else return response1;
}

void DefaultContactManager::draw()
{
    for (sofa::helper::vector<core::collision::Contact*>::iterator it = contacts.begin(); it!=contacts.end(); it++)
    {
        if ((*it)!=NULL)
            (*it)->draw();
    }
}

void DefaultContactManager::removeContacts(const ContactVector &c)
{
    ContactVector::const_iterator remove_it = c.begin();
    ContactVector::const_iterator remove_itEnd = c.end();

    ContactVector::iterator it;
    ContactVector::iterator itEnd;

    ContactMap::iterator map_it;
    ContactMap::iterator map_itEnd;

    while (remove_it != remove_itEnd)
    {
        // Whole scene contacts
        it = contacts.begin();
        itEnd = contacts.end();

        while (it != itEnd)
        {
            if (*it == *remove_it)
            {
                contacts.erase(it);
                break;
            }

            ++it;
        }

        // Stored contacts (keeping alive)
        map_it = contactMap.begin();
        map_itEnd = contactMap.end();

        while (map_it != map_itEnd)
        {
            if (map_it->second == *remove_it)
            {
                ContactMap::iterator erase_it = map_it;
                ++map_it;
                contactMap.erase(erase_it);
            }
            else
            {
                ++map_it;
            }
        }

        ++remove_it;
    }

}

} // namespace collision

} // namespace component

} // namespace sofa
<commit_msg>r7657/sofa-dev : FIX: bad init of the DefaultContactManager<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/component/collision/DefaultContactManager.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace collision
{

SOFA_DECL_CLASS(DefaultContactManager)

int DefaultContactManagerClass = core::RegisterObject("Default class to create reactions to the collisions")
        .add< DefaultContactManager >()
        .addAlias("CollisionResponse")
        ;

DefaultContactManager::DefaultContactManager()
    : response(initData(&response, "response", "contact response class"))
{
}

DefaultContactManager::~DefaultContactManager()
{
    // Contacts are now attached to the graph.
    // So they will be deleted by the DeleteVisitor
    // FIX crash on unload bug. -- J. Allard
    //clear();
}

sofa::helper::OptionsGroup DefaultContactManager::initializeResponseOptions(core::collision::Pipeline *pipeline)
{
    helper::set<std::string> listResponse;
    if (pipeline) listResponse=pipeline->getResponseList();
    else
    {
        core::collision::Contact::Factory::iterator it;
        for (it=core::collision::Contact::Factory::getInstance()->begin(); it!=core::collision::Contact::Factory::getInstance()->end(); ++it)
        {
            listResponse.insert(it->first);
        }
    }
    sofa::helper::OptionsGroup responseOptions(listResponse);
    if (listResponse.find("default") != listResponse.end())
        responseOptions.setSelectedItem("default");
    return responseOptions;
}

void DefaultContactManager::init()
{
    if (response.getValue().size() == 0)
    {
        core::collision::Pipeline *pipeline=static_cast<simulation::Node*>(getContext())->collisionPipeline;
        response.setValue(initializeResponseOptions(pipeline));
    }
}
void DefaultContactManager::cleanup()
{
    for (sofa::helper::vector<core::collision::Contact*>::iterator it=contacts.begin(); it!=contacts.end(); ++it)
    {
        (*it)->removeResponse();
        (*it)->cleanup();
        delete *it;
    }
    contacts.clear();
    contactMap.clear();
}

void DefaultContactManager::createContacts(DetectionOutputMap& outputsMap)
{
    //serr<<"DefaultContactManager::createContacts"<<sendl;

    //outputsMap.clear();
    //for (sofa::helper::vector<core::collision::DetectionOutput*>::const_iterator it = outputs.begin(); it!=outputs.end(); ++it)
    //{
    //	core::collision::DetectionOutput* o = *it;
    //	outputsMap[std::make_pair(o->elem.first.getCollisionModel(),o->elem.second.getCollisionModel())].push_back(o);
    //}

    // Remove any inactive contacts or add any new contact
    DetectionOutputMap::iterator outputsIt = outputsMap.begin();
    std::map< std::pair<core::CollisionModel*,core::CollisionModel*>, core::collision::Contact* >::iterator contactIt = contactMap.begin();
    int nbContact = 0;
    //static DetectionOutputVector emptyContacts;
    while (outputsIt!=outputsMap.end() || contactIt!=contactMap.end())
    {
        if (outputsIt!=outputsMap.end() && (contactIt == contactMap.end() || outputsIt->first < contactIt->first))
        {
            // new contact
            //sout << "Creation new "<<contacttype<<" contact"<<sendl;
            core::CollisionModel* model1 = outputsIt->first.first;
            core::CollisionModel* model2 = outputsIt->first.second;
            std::string responseUsed = getContactResponse(model1, model2);
            core::collision::Contact* contact = core::collision::Contact::Create(responseUsed, model1, model2, intersectionMethod);
            if (contact == NULL) serr << "Contact "<<responseUsed<<" between " << model1->getClassName()<<" and "<<model2->getClassName() << " creation failed"<<sendl;
            else
            {
                contactMap[std::make_pair(model1, model2)] = contact;
                contact->setName(model1->getName()+std::string("-")+model2->getName());
                contact->f_printLog.setValue(this->f_printLog.getValue());
                contact->init();
                contact->setDetectionOutputs(outputsIt->second);
                ++nbContact;
            }
            ++outputsIt;
        }
        else if (contactIt!=contactMap.end() && (outputsIt == outputsMap.end() || contactIt->first < outputsIt->first))
        {
            // inactive contact
            //sout << "Deleting inactive "<<contacttype<<" contact"<<sendl;
            if (contactIt->second->keepAlive())
            {
                contactIt->second->setDetectionOutputs(NULL);
                ++nbContact;
                ++contactIt;
            }
            else
            {
                std::map< std::pair<core::CollisionModel*,core::CollisionModel*>, core::collision::Contact* >::iterator contactIt2 = contactIt;
                ++contactIt2;
                contactIt->second->removeResponse();
                contactIt->second->cleanup();
                delete contactIt->second;
                contactMap.erase(contactIt);
                contactIt = contactIt2;
            }
        }
        else
        {
            // corresponding contact and outputs
            contactIt->second->setDetectionOutputs(outputsIt->second);
            ++nbContact;
            ++outputsIt;
            ++contactIt;
        }
    }
    // now update contactVec
    contacts.clear();
    contacts.reserve(nbContact);
    contactIt = contactMap.begin();
    while (contactIt!=contactMap.end())
    {
        contacts.push_back(contactIt->second);
        ++contactIt;
    }
    // compute number of contacts attached to each collision model
    std::map<core::CollisionModel*,int> nbContactsMap;
    for (unsigned int i=0; i<contacts.size(); ++i)
    {
        std::pair< core::CollisionModel*, core::CollisionModel* > cms = contacts[i]->getCollisionModels();
        nbContactsMap[cms.first]++;
        if (cms.second != cms.first)
            nbContactsMap[cms.second]++;
    }
    sofa::helper::vector<core::CollisionModel*> collisionModels;
    simulation::Node* context = dynamic_cast<simulation::Node*>(getContext());
    context->getTreeObjects<core::CollisionModel>(&collisionModels);
    for (unsigned int i=0; i<collisionModels.size(); ++i)
    {
        collisionModels[i]->setNumberOfContacts(nbContactsMap[collisionModels[i]]);
    }
}

std::string DefaultContactManager::getContactResponse(core::CollisionModel* model1, core::CollisionModel* model2)
{
    std::string responseUsed = response.getValue().getSelectedItem();
    std::string response1 = model1->getContactResponse();
    std::string response2 = model2->getContactResponse();

    if (response1.empty()  &&  response2.empty()) return responseUsed;
    if (response1.empty()  && !response2.empty()) return response2;
    if (!response1.empty() &&  response2.empty()) return response1;

    if (response1 != response2) return responseUsed;
    else return response1;
}

void DefaultContactManager::draw()
{
    for (sofa::helper::vector<core::collision::Contact*>::iterator it = contacts.begin(); it!=contacts.end(); it++)
    {
        if ((*it)!=NULL)
            (*it)->draw();
    }
}

void DefaultContactManager::removeContacts(const ContactVector &c)
{
    ContactVector::const_iterator remove_it = c.begin();
    ContactVector::const_iterator remove_itEnd = c.end();

    ContactVector::iterator it;
    ContactVector::iterator itEnd;

    ContactMap::iterator map_it;
    ContactMap::iterator map_itEnd;

    while (remove_it != remove_itEnd)
    {
        // Whole scene contacts
        it = contacts.begin();
        itEnd = contacts.end();

        while (it != itEnd)
        {
            if (*it == *remove_it)
            {
                contacts.erase(it);
                break;
            }

            ++it;
        }

        // Stored contacts (keeping alive)
        map_it = contactMap.begin();
        map_itEnd = contactMap.end();

        while (map_it != map_itEnd)
        {
            if (map_it->second == *remove_it)
            {
                ContactMap::iterator erase_it = map_it;
                ++map_it;
                contactMap.erase(erase_it);
            }
            else
            {
                ++map_it;
            }
        }

        ++remove_it;
    }

}

} // namespace collision

} // namespace component

} // namespace sofa
<|endoftext|>


<commit_before>#ifndef SOFA_COMPONENT_FORCEFIELD_MESHSPRINGFORCEFIELD_INL
#define SOFA_COMPONENT_FORCEFIELD_MESHSPRINGFORCEFIELD_INL

#include <sofa/component/forcefield/MeshSpringForceField.h>
#include <sofa/component/forcefield/StiffSpringForceField.inl>
#include <sofa/component/topology/MeshTopology.h>
#include <iostream>
using std::cerr;
using std::endl;

namespace sofa
{

namespace component
{

namespace forcefield
{

template <class DataTypes>
double MeshSpringForceField<DataTypes>::getPotentialEnergy()
{
    cerr<<"MeshSpringForceField::getPotentialEnergy-not-implemented !!!"<<endl;
    return 0;
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::addSpring(std::set<std::pair<int,int> >& sset, int m1, int m2, Real stiffness, Real damping)
{
    if (m1<m2)
    {
        if (sset.count(std::make_pair(m1,m2))>0) return;
        sset.insert(std::make_pair(m1,m2));
    }
    else
    {
        if (sset.count(std::make_pair(m2,m1))>0) return;
        sset.insert(std::make_pair(m2,m1));
    }
    Real l = ((*this->object2->getX())[m2] - (*this->object1->getX())[m1]).norm();
    this->springs.push_back(typename SpringForceField<DataTypes>::Spring(m1,m2,stiffness/l, damping/l, l));
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::init()
{
    assert(this->object1);
    assert(this->object2);
    if(!object1 || !object2)
        this->object2 = this->object1 = dynamic_cast<sofa::core::componentmodel::behavior::MechanicalState<DataTypes> *>(this->getContext()->getMechanicalState());

    if (this->object1==this->object2)
    {
        topology::MeshTopology* topology = dynamic_cast<topology::MeshTopology*>(this->object1->getContext()->getTopology());
        if (topology != NULL)
        {
            std::set< std::pair<int,int> > sset;
            int n;
            Real s, d;
            if (this->linesStiffness != 0.0 || this->linesDamping != 0.0)
            {
                s = this->linesStiffness;
                d = this->linesDamping;
                n = topology->getNbLines();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Line e = topology->getLine(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                }
            }
            if (this->trianglesStiffness != 0.0 || this->trianglesDamping != 0.0)
            {
                s = this->trianglesStiffness;
                d = this->trianglesDamping;
                n = topology->getNbTriangles();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Triangle e = topology->getTriangle(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                }
            }
            if (this->quadsStiffness != 0.0 || this->quadsDamping != 0.0)
            {
                s = this->quadsStiffness;
                d = this->quadsDamping;
                n = topology->getNbQuads();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Quad e = topology->getQuad(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[0], e[3], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                    this->addSpring(sset, e[1], e[3], s, d);
                    this->addSpring(sset, e[2], e[3], s, d);
                }
            }
            if (this->tetrasStiffness != 0.0 || this->tetrasDamping != 0.0)
            {
                s = this->tetrasStiffness;
                d = this->tetrasDamping;
                n = topology->getNbTetras();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Tetra e = topology->getTetra(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[0], e[3], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                    this->addSpring(sset, e[1], e[3], s, d);
                    this->addSpring(sset, e[2], e[3], s, d);
                }
            }
            if (this->cubesStiffness != 0.0 || this->cubesDamping != 0.0)
            {
                s = this->cubesStiffness;
                d = this->cubesDamping;
                n = topology->getNbCubes();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Cube e = topology->getCube(i);
                    for (int i=0; i<8; i++)
                        for (int j=i+1; j<8; j++)
                            this->addSpring(sset, e[i], e[j], s, d);
                }
            }
        }
    }
    this->StiffSpringForceField<DataTypes>::init();
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
{
    this->StiffSpringForceField<DataTypes>::parse(arg);
    if (arg->getAttribute("stiffness"))          this->setStiffness         ((Real)atof(arg->getAttribute("stiffness")));
    if (arg->getAttribute("linesStiffness"))     this->setLinesStiffness    ((Real)atof(arg->getAttribute("linesStiffness")));
    if (arg->getAttribute("trianglesStiffness")) this->setTrianglesStiffness((Real)atof(arg->getAttribute("trianglesStiffness")));
    if (arg->getAttribute("quadsStiffness"))     this->setQuadsStiffness    ((Real)atof(arg->getAttribute("quadsStiffness")));
    if (arg->getAttribute("tetrasStiffness"))    this->setTetrasStiffness   ((Real)atof(arg->getAttribute("tetrasStiffness")));
    if (arg->getAttribute("cubesStiffness"))     this->setCubesStiffness    ((Real)atof(arg->getAttribute("cubesStiffness")));
    if (arg->getAttribute("damping"))            this->setDamping           ((Real)atof(arg->getAttribute("damping")));
    if (arg->getAttribute("linesDamping"))       this->setLinesDamping      ((Real)atof(arg->getAttribute("linesDamping")));
    if (arg->getAttribute("trianglesDamping"))   this->setTrianglesDamping  ((Real)atof(arg->getAttribute("trianglesDamping")));
    if (arg->getAttribute("quadsDamping"))       this->setQuadsDamping      ((Real)atof(arg->getAttribute("quadsDamping")));
    if (arg->getAttribute("tetrasDamping"))      this->setTetrasDamping     ((Real)atof(arg->getAttribute("tetrasDamping")));
    if (arg->getAttribute("cubesDamping"))       this->setCubesDamping      ((Real)atof(arg->getAttribute("cubesDamping")));
}

} // namespace forcefield

} // namespace component

} // namespace sofa

#endif
<commit_msg>r865/sofa-dev : FIX : linux compilation<commit_after>#ifndef SOFA_COMPONENT_FORCEFIELD_MESHSPRINGFORCEFIELD_INL
#define SOFA_COMPONENT_FORCEFIELD_MESHSPRINGFORCEFIELD_INL

#include <sofa/component/forcefield/MeshSpringForceField.h>
#include <sofa/component/forcefield/StiffSpringForceField.inl>
#include <sofa/component/topology/MeshTopology.h>
#include <iostream>
using std::cerr;
using std::endl;

namespace sofa
{

namespace component
{

namespace forcefield
{

template <class DataTypes>
double MeshSpringForceField<DataTypes>::getPotentialEnergy()
{
    cerr<<"MeshSpringForceField::getPotentialEnergy-not-implemented !!!"<<endl;
    return 0;
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::addSpring(std::set<std::pair<int,int> >& sset, int m1, int m2, Real stiffness, Real damping)
{
    if (m1<m2)
    {
        if (sset.count(std::make_pair(m1,m2))>0) return;
        sset.insert(std::make_pair(m1,m2));
    }
    else
    {
        if (sset.count(std::make_pair(m2,m1))>0) return;
        sset.insert(std::make_pair(m2,m1));
    }
    Real l = ((*this->object2->getX())[m2] - (*this->object1->getX())[m1]).norm();
    this->springs.push_back(typename SpringForceField<DataTypes>::Spring(m1,m2,stiffness/l, damping/l, l));
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::init()
{
    assert(this->object1);
    assert(this->object2);
    if(!(this->object1) || !(this->object2))
        this->object2 = this->object1 = dynamic_cast<sofa::core::componentmodel::behavior::MechanicalState<DataTypes> *>(this->getContext()->getMechanicalState());

    if (this->object1==this->object2)
    {
        topology::MeshTopology* topology = dynamic_cast<topology::MeshTopology*>(this->object1->getContext()->getTopology());
        if (topology != NULL)
        {
            std::set< std::pair<int,int> > sset;
            int n;
            Real s, d;
            if (this->linesStiffness != 0.0 || this->linesDamping != 0.0)
            {
                s = this->linesStiffness;
                d = this->linesDamping;
                n = topology->getNbLines();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Line e = topology->getLine(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                }
            }
            if (this->trianglesStiffness != 0.0 || this->trianglesDamping != 0.0)
            {
                s = this->trianglesStiffness;
                d = this->trianglesDamping;
                n = topology->getNbTriangles();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Triangle e = topology->getTriangle(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                }
            }
            if (this->quadsStiffness != 0.0 || this->quadsDamping != 0.0)
            {
                s = this->quadsStiffness;
                d = this->quadsDamping;
                n = topology->getNbQuads();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Quad e = topology->getQuad(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[0], e[3], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                    this->addSpring(sset, e[1], e[3], s, d);
                    this->addSpring(sset, e[2], e[3], s, d);
                }
            }
            if (this->tetrasStiffness != 0.0 || this->tetrasDamping != 0.0)
            {
                s = this->tetrasStiffness;
                d = this->tetrasDamping;
                n = topology->getNbTetras();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Tetra e = topology->getTetra(i);
                    this->addSpring(sset, e[0], e[1], s, d);
                    this->addSpring(sset, e[0], e[2], s, d);
                    this->addSpring(sset, e[0], e[3], s, d);
                    this->addSpring(sset, e[1], e[2], s, d);
                    this->addSpring(sset, e[1], e[3], s, d);
                    this->addSpring(sset, e[2], e[3], s, d);
                }
            }
            if (this->cubesStiffness != 0.0 || this->cubesDamping != 0.0)
            {
                s = this->cubesStiffness;
                d = this->cubesDamping;
                n = topology->getNbCubes();
                for (int i=0; i<n; ++i)
                {
                    topology::MeshTopology::Cube e = topology->getCube(i);
                    for (int i=0; i<8; i++)
                        for (int j=i+1; j<8; j++)
                            this->addSpring(sset, e[i], e[j], s, d);
                }
            }
        }
    }
    this->StiffSpringForceField<DataTypes>::init();
}

template<class DataTypes>
void MeshSpringForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
{
    this->StiffSpringForceField<DataTypes>::parse(arg);
    if (arg->getAttribute("stiffness"))          this->setStiffness         ((Real)atof(arg->getAttribute("stiffness")));
    if (arg->getAttribute("linesStiffness"))     this->setLinesStiffness    ((Real)atof(arg->getAttribute("linesStiffness")));
    if (arg->getAttribute("trianglesStiffness")) this->setTrianglesStiffness((Real)atof(arg->getAttribute("trianglesStiffness")));
    if (arg->getAttribute("quadsStiffness"))     this->setQuadsStiffness    ((Real)atof(arg->getAttribute("quadsStiffness")));
    if (arg->getAttribute("tetrasStiffness"))    this->setTetrasStiffness   ((Real)atof(arg->getAttribute("tetrasStiffness")));
    if (arg->getAttribute("cubesStiffness"))     this->setCubesStiffness    ((Real)atof(arg->getAttribute("cubesStiffness")));
    if (arg->getAttribute("damping"))            this->setDamping           ((Real)atof(arg->getAttribute("damping")));
    if (arg->getAttribute("linesDamping"))       this->setLinesDamping      ((Real)atof(arg->getAttribute("linesDamping")));
    if (arg->getAttribute("trianglesDamping"))   this->setTrianglesDamping  ((Real)atof(arg->getAttribute("trianglesDamping")));
    if (arg->getAttribute("quadsDamping"))       this->setQuadsDamping      ((Real)atof(arg->getAttribute("quadsDamping")));
    if (arg->getAttribute("tetrasDamping"))      this->setTetrasDamping     ((Real)atof(arg->getAttribute("tetrasDamping")));
    if (arg->getAttribute("cubesDamping"))       this->setCubesDamping      ((Real)atof(arg->getAttribute("cubesDamping")));
}

} // namespace forcefield

} // namespace component

} // namespace sofa

#endif
<|endoftext|>


<commit_before>#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#include <fuse.h>

using namespace std;

static const char *image_path = "/sparsebundle.dmg";

struct sparsebundle_data {
    char *path;
    off_t band_size;
    off_t size;
    FILE *logfile;
};

#define SB_DATA_CAST(ptr) ((struct sparsebundle_data *) ptr)
#define SB_DATA (SB_DATA_CAST(fuse_get_context()->private_data))

static int sparsebundle_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
              off_t offset, struct fuse_file_info *fi)
{
    if (strcmp(path, "/") != 0)
        return -ENOENT;

    filler(buf, ".", 0, 0);
    filler(buf, "..", 0, 0);
    filler(buf, image_path + 1, 0, 0);

    return 0;
}

static int sparsebundle_getattr(const char *path, struct stat *stbuf)
{
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 3;
    } else if (strcmp(path, image_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = SB_DATA->size;
    } else
        return -ENOENT;

    return 0;
}

static int sparsebundle_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if ((fi->flags & O_ACCMODE) != O_RDONLY)
        return -EACCES;

    return 0;
}

static void log(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    vfprintf(SB_DATA->logfile, format, ap);
}

static int sparsebundle_read(const char *path, char *buffer, size_t length, off_t offset,
           struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if (offset >= SB_DATA->size)
        return 0;

    if (offset + length > SB_DATA->size)
        length = SB_DATA->size - offset;

    log("sparsebundle_read(length: %zu offfset: %llu\n", length, offset);

    size_t bytes_read = 0;
    while (bytes_read < length) {
        off_t band_number = (offset + bytes_read) / SB_DATA->band_size;
        off_t band_offset = (offset + bytes_read) % SB_DATA->band_size;

        ssize_t to_read = length - bytes_read;

        char *band_name;
        asprintf(&band_name, "%s/bands/%llx", SB_DATA->path, band_number);

        log("\tReading band %llx at offet %llu (bytes_read: %zu to_read: %zu\n",
            band_number, band_offset, bytes_read, to_read);

        ssize_t read = 0;
        int band_file = open(band_name, O_RDONLY);
        if (band_file != -1) {
            read = pread(band_file, buffer + bytes_read, to_read, band_offset);
            close(band_file);

            if (read == -1) {
                log("! Failed to read %zu bytes from band file %s at offset %llu\n",
                    to_read, band_name, band_offset);
                free(band_name);
                return -1;
            }
        } else if (errno != ENOENT) {
            log("! Failed to open band file %s %d\n", band_name, errno);
            free(band_name);
            return -1;
        }

        free(band_name);

        if (read < to_read) {
            log("! EOB, read: %zu, padding with zeroes\n", read);
            // Hit missing band or end of band, pad with zeroes
            memset(buffer + bytes_read + read, 0, to_read - read);
        }

        bytes_read += to_read;
    }

    assert(bytes_read == length);
    return bytes_read;
}

static int sparsebundle_show_usage(char *program_name)
{
    fprintf(stderr, "usage: %s [-o options] sparsebundle mountpoint\n", program_name);
    return 1;
}

static int sparsebundle_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
    if (key == FUSE_OPT_KEY_NONOPT && !SB_DATA_CAST(data)->path) {
        SB_DATA_CAST(data)->path = strdup(arg);
        return 0;
    }

    return 1;
}

static off_t read_size(const string &str)
{
    uintmax_t value = strtoumax(str.c_str(), 0, 10);
    if (errno == ERANGE || value > static_cast<uintmax_t>(numeric_limits<off_t>::max())) {
        fprintf(stderr, "Disk image too large to be mounted (%s bytes)\n", str.c_str());
        exit(-1);
    }

    return value;
}

int main(int argc, char **argv)
{
    struct sparsebundle_data data = {};

    data.logfile = fopen("/tmp/sparesebundlefs.log", "w");
    setvbuf(data.logfile, 0, _IOLBF, 0);

    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    fuse_opt_parse(&args, &data, 0, sparsebundle_opt_proc);

    if (!data.path)
        return sparsebundle_show_usage(argv[0]);

    char *abs_path = realpath(data.path, 0);
    if (!abs_path) {
        perror("Could not resolve absolute path");
        return -1;
    }

    free(data.path);
    data.path = abs_path;

    char *plist_path;
    asprintf(&plist_path, "%s/Info.plist", data.path);

    ifstream plist_file(plist_path);
    stringstream plist_data;
    plist_data << plist_file.rdbuf();

    string key, line;
    while (getline(plist_data, line)) {
        static const char *whitespace_chars = " \n\r\t";
        line.erase(0, line.find_first_not_of(whitespace_chars));
        line.erase(line.find_last_not_of(whitespace_chars) + 1);

        if (line.compare(0, 5, "<key>") == 0) {
            key = line.substr(5, line.length() - 11);
        } else if (!key.empty()) {
            line.erase(0, line.find_first_of('>') + 1);
            line.erase(line.find_first_of('<'));

            if (key == "band-size")
                data.band_size = read_size(line);
            else if (key == "size")
                data.size = read_size(line);

            key.clear();
        }
    }

    struct fuse_operations sparsebundle_filesystem_operations = {};
    sparsebundle_filesystem_operations.getattr = sparsebundle_getattr;
    sparsebundle_filesystem_operations.open = sparsebundle_open;
    sparsebundle_filesystem_operations.read = sparsebundle_read;
    sparsebundle_filesystem_operations.readdir = sparsebundle_readdir;

    int ret = fuse_main(args.argc, args.argv, &sparsebundle_filesystem_operations, &data);

    fuse_opt_free_args(&args);
    return ret;
}
<commit_msg>Remove duplicate include<commit_after>#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

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

#include <fuse.h>

using namespace std;

static const char *image_path = "/sparsebundle.dmg";

struct sparsebundle_data {
    char *path;
    off_t band_size;
    off_t size;
    FILE *logfile;
};

#define SB_DATA_CAST(ptr) ((struct sparsebundle_data *) ptr)
#define SB_DATA (SB_DATA_CAST(fuse_get_context()->private_data))

static int sparsebundle_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
              off_t offset, struct fuse_file_info *fi)
{
    if (strcmp(path, "/") != 0)
        return -ENOENT;

    filler(buf, ".", 0, 0);
    filler(buf, "..", 0, 0);
    filler(buf, image_path + 1, 0, 0);

    return 0;
}

static int sparsebundle_getattr(const char *path, struct stat *stbuf)
{
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 3;
    } else if (strcmp(path, image_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = SB_DATA->size;
    } else
        return -ENOENT;

    return 0;
}

static int sparsebundle_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if ((fi->flags & O_ACCMODE) != O_RDONLY)
        return -EACCES;

    return 0;
}

static void log(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    vfprintf(SB_DATA->logfile, format, ap);
}

static int sparsebundle_read(const char *path, char *buffer, size_t length, off_t offset,
           struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if (offset >= SB_DATA->size)
        return 0;

    if (offset + length > SB_DATA->size)
        length = SB_DATA->size - offset;

    log("sparsebundle_read(length: %zu offfset: %llu\n", length, offset);

    size_t bytes_read = 0;
    while (bytes_read < length) {
        off_t band_number = (offset + bytes_read) / SB_DATA->band_size;
        off_t band_offset = (offset + bytes_read) % SB_DATA->band_size;

        ssize_t to_read = length - bytes_read;

        char *band_name;
        asprintf(&band_name, "%s/bands/%llx", SB_DATA->path, band_number);

        log("\tReading band %llx at offet %llu (bytes_read: %zu to_read: %zu\n",
            band_number, band_offset, bytes_read, to_read);

        ssize_t read = 0;
        int band_file = open(band_name, O_RDONLY);
        if (band_file != -1) {
            read = pread(band_file, buffer + bytes_read, to_read, band_offset);
            close(band_file);

            if (read == -1) {
                log("! Failed to read %zu bytes from band file %s at offset %llu\n",
                    to_read, band_name, band_offset);
                free(band_name);
                return -1;
            }
        } else if (errno != ENOENT) {
            log("! Failed to open band file %s %d\n", band_name, errno);
            free(band_name);
            return -1;
        }

        free(band_name);

        if (read < to_read) {
            log("! EOB, read: %zu, padding with zeroes\n", read);
            // Hit missing band or end of band, pad with zeroes
            memset(buffer + bytes_read + read, 0, to_read - read);
        }

        bytes_read += to_read;
    }

    assert(bytes_read == length);
    return bytes_read;
}

static int sparsebundle_show_usage(char *program_name)
{
    fprintf(stderr, "usage: %s [-o options] sparsebundle mountpoint\n", program_name);
    return 1;
}

static int sparsebundle_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
    if (key == FUSE_OPT_KEY_NONOPT && !SB_DATA_CAST(data)->path) {
        SB_DATA_CAST(data)->path = strdup(arg);
        return 0;
    }

    return 1;
}

static off_t read_size(const string &str)
{
    uintmax_t value = strtoumax(str.c_str(), 0, 10);
    if (errno == ERANGE || value > static_cast<uintmax_t>(numeric_limits<off_t>::max())) {
        fprintf(stderr, "Disk image too large to be mounted (%s bytes)\n", str.c_str());
        exit(-1);
    }

    return value;
}

int main(int argc, char **argv)
{
    struct sparsebundle_data data = {};

    data.logfile = fopen("/tmp/sparesebundlefs.log", "w");
    setvbuf(data.logfile, 0, _IOLBF, 0);

    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    fuse_opt_parse(&args, &data, 0, sparsebundle_opt_proc);

    if (!data.path)
        return sparsebundle_show_usage(argv[0]);

    char *abs_path = realpath(data.path, 0);
    if (!abs_path) {
        perror("Could not resolve absolute path");
        return -1;
    }

    free(data.path);
    data.path = abs_path;

    char *plist_path;
    asprintf(&plist_path, "%s/Info.plist", data.path);

    ifstream plist_file(plist_path);
    stringstream plist_data;
    plist_data << plist_file.rdbuf();

    string key, line;
    while (getline(plist_data, line)) {
        static const char *whitespace_chars = " \n\r\t";
        line.erase(0, line.find_first_not_of(whitespace_chars));
        line.erase(line.find_last_not_of(whitespace_chars) + 1);

        if (line.compare(0, 5, "<key>") == 0) {
            key = line.substr(5, line.length() - 11);
        } else if (!key.empty()) {
            line.erase(0, line.find_first_of('>') + 1);
            line.erase(line.find_first_of('<'));

            if (key == "band-size")
                data.band_size = read_size(line);
            else if (key == "size")
                data.size = read_size(line);

            key.clear();
        }
    }

    struct fuse_operations sparsebundle_filesystem_operations = {};
    sparsebundle_filesystem_operations.getattr = sparsebundle_getattr;
    sparsebundle_filesystem_operations.open = sparsebundle_open;
    sparsebundle_filesystem_operations.read = sparsebundle_read;
    sparsebundle_filesystem_operations.readdir = sparsebundle_readdir;

    int ret = fuse_main(args.argc, args.argv, &sparsebundle_filesystem_operations, &data);

    fuse_opt_free_args(&args);
    return ret;
}
<|endoftext|>


<commit_before>#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <fuse.h>
#include <stdlib.h>
#include <stdio.h>

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

static const char *image_path = "/sparsebundle.dmg";

struct sparsebundle_data {
    char *path;
    int band_size;
    int size;
    FILE* logfile;
};

#define SB_DATA_CAST(ptr) ((struct sparsebundle_data *) ptr)
#define SB_DATA (SB_DATA_CAST(fuse_get_context()->private_data))

static int sparsebundle_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
              off_t offset, struct fuse_file_info *fi)
{
    if (strcmp(path, "/") != 0)
        return -ENOENT;

    filler(buf, ".", 0, 0);
    filler(buf, "..", 0, 0);
    filler(buf, image_path + 1, 0, 0);

    return 0;
}

static int sparsebundle_getattr(const char *path, struct stat *stbuf)
{
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 3;
    } else if (strcmp(path, image_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = SB_DATA->size;
    } else
        return -ENOENT;

    return 0;
}

static int sparsebundle_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if ((fi->flags & O_ACCMODE) != O_RDONLY)
        return -EACCES;

    return 0;
}

static void log(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    vfprintf(SB_DATA->logfile, format, ap);
}

static int sparsebundle_read(const char *path, char *buffer, size_t length, off_t offset,
           struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if (offset >= SB_DATA->size)
        return 0;

    if (offset + length > SB_DATA->size)
        length = SB_DATA->size - offset;

    log("sparsebundle_read(length: %zu offfset: %llu\n", length, offset);

    size_t bytes_read = 0;
    while (bytes_read < length) {
        off_t band_number = (offset + bytes_read) / SB_DATA->band_size;
        off_t band_offset = (offset + bytes_read) % SB_DATA->band_size;

        size_t to_read = length - bytes_read;

        char *band_name;
        asprintf(&band_name, "%s/bands/%jd", SB_DATA->path, intmax_t(band_number));

        log("\tReading band %llu at offet %llu (bytes_read: %zu to_read: %zu\n",
            band_number, band_offset, bytes_read, to_read);

        size_t read = 0;
        int band_file = open(band_name, O_RDONLY);
        if (band_file != -1) {
            read = pread(band_file, buffer + bytes_read, to_read, band_offset);
            close(band_file);

            if (read == -1) {
                log("! Failed to read %zu bytes from band file %s at offset %llu\n",
                    to_read, band_name, band_offset);
                free(band_name);
                return -1;
            }
        } else if (errno != ENOENT) {
            log("! Failed to open band file %s %d\n", band_name, errno);
            free(band_name);
            return -1;
        }

        free(band_name);

        if (read < to_read) {
            log("! EOB, read: %zu, padding with zeroes\n", read);
            // Hit missing band or end of band, pad with zeroes
            memset(buffer + bytes_read + read, 0, to_read - read);
        }

        bytes_read += to_read;
    }

    assert(bytes_read == length);
    return bytes_read;
}

static int sparsebundle_show_usage(char* program_name)
{
    fprintf(stderr, "usage: %s [-o options] sparsebundle mountpoint\n", program_name);
    return 1;
}

static struct fuse_operations sparsebundle_filesystem_operations = {
    .getattr = sparsebundle_getattr,
    .open    = sparsebundle_open,
    .read    = sparsebundle_read,
    .readdir = sparsebundle_readdir,
};

static int sparsebundle_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
    if (key == FUSE_OPT_KEY_NONOPT && !SB_DATA_CAST(data)->path) {
        SB_DATA_CAST(data)->path = strdup(arg);
        return 0;
    }

    return 1;
}

using namespace std;

int main(int argc, char **argv)
{
    struct sparsebundle_data data = {};

    data.logfile = fopen("/tmp/sparesebundlefs.log", "w");
    setvbuf(data.logfile, 0, _IOLBF, 0);

    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    fuse_opt_parse(&args, &data, 0, sparsebundle_opt_proc);

    if (!data.path)
        return sparsebundle_show_usage(argv[0]);

    char *abs_path = realpath(data.path, 0);
    if (!abs_path) {
        perror("Could not resolve absolute path");
        return -1;
    }

    free(data.path);
    data.path = abs_path;

    char *plist_path;
    asprintf(&plist_path, "%s/Info.plist", data.path);

    ifstream plist_file(plist_path);
    stringstream plist_data;
    plist_data << plist_file.rdbuf();

    string key, line;
    while (getline(plist_data, line)) {
        static const char *whitespace_chars = " \n\r\t";
        line.erase(0, line.find_first_not_of(whitespace_chars));
        line.erase(line.find_last_not_of(whitespace_chars) + 1);

        if (line.compare(0, 5, "<key>") == 0) {
            key = line.substr(5, line.length() - 11);
        } else if (!key.empty()) {
            line.erase(0, line.find_first_of('>') + 1);
            line.erase(line.find_first_of('<'));

            if (key == "band-size") {
                data.band_size = atoi(line.c_str());
            } else if (key == "size") {
                data.size = atoi(line.c_str());
            }

            key.clear();
        }
    }

    int ret = fuse_main(args.argc, args.argv, &sparsebundle_filesystem_operations, &data);

    fuse_opt_free_args(&args);
    return ret;
}
<commit_msg>Fix warning about signed and unsigned comparison<commit_after>#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <fuse.h>
#include <stdlib.h>
#include <stdio.h>

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

static const char *image_path = "/sparsebundle.dmg";

struct sparsebundle_data {
    char *path;
    int band_size;
    int size;
    FILE* logfile;
};

#define SB_DATA_CAST(ptr) ((struct sparsebundle_data *) ptr)
#define SB_DATA (SB_DATA_CAST(fuse_get_context()->private_data))

static int sparsebundle_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
              off_t offset, struct fuse_file_info *fi)
{
    if (strcmp(path, "/") != 0)
        return -ENOENT;

    filler(buf, ".", 0, 0);
    filler(buf, "..", 0, 0);
    filler(buf, image_path + 1, 0, 0);

    return 0;
}

static int sparsebundle_getattr(const char *path, struct stat *stbuf)
{
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 3;
    } else if (strcmp(path, image_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = SB_DATA->size;
    } else
        return -ENOENT;

    return 0;
}

static int sparsebundle_open(const char *path, struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if ((fi->flags & O_ACCMODE) != O_RDONLY)
        return -EACCES;

    return 0;
}

static void log(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    vfprintf(SB_DATA->logfile, format, ap);
}

static int sparsebundle_read(const char *path, char *buffer, size_t length, off_t offset,
           struct fuse_file_info *fi)
{
    if (strcmp(path, image_path) != 0)
        return -ENOENT;

    if (offset >= SB_DATA->size)
        return 0;

    if (offset + length > SB_DATA->size)
        length = SB_DATA->size - offset;

    log("sparsebundle_read(length: %zu offfset: %llu\n", length, offset);

    size_t bytes_read = 0;
    while (bytes_read < length) {
        off_t band_number = (offset + bytes_read) / SB_DATA->band_size;
        off_t band_offset = (offset + bytes_read) % SB_DATA->band_size;

        size_t to_read = length - bytes_read;

        char *band_name;
        asprintf(&band_name, "%s/bands/%jd", SB_DATA->path, intmax_t(band_number));

        log("\tReading band %llu at offet %llu (bytes_read: %zu to_read: %zu\n",
            band_number, band_offset, bytes_read, to_read);

        ssize_t read = 0;
        int band_file = open(band_name, O_RDONLY);
        if (band_file != -1) {
            read = pread(band_file, buffer + bytes_read, to_read, band_offset);
            close(band_file);

            if (read == -1) {
                log("! Failed to read %zu bytes from band file %s at offset %llu\n",
                    to_read, band_name, band_offset);
                free(band_name);
                return -1;
            }
        } else if (errno != ENOENT) {
            log("! Failed to open band file %s %d\n", band_name, errno);
            free(band_name);
            return -1;
        }

        free(band_name);

        if (read < to_read) {
            log("! EOB, read: %zu, padding with zeroes\n", read);
            // Hit missing band or end of band, pad with zeroes
            memset(buffer + bytes_read + read, 0, to_read - read);
        }

        bytes_read += to_read;
    }

    assert(bytes_read == length);
    return bytes_read;
}

static int sparsebundle_show_usage(char* program_name)
{
    fprintf(stderr, "usage: %s [-o options] sparsebundle mountpoint\n", program_name);
    return 1;
}

static struct fuse_operations sparsebundle_filesystem_operations = {
    .getattr = sparsebundle_getattr,
    .open    = sparsebundle_open,
    .read    = sparsebundle_read,
    .readdir = sparsebundle_readdir,
};

static int sparsebundle_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
    if (key == FUSE_OPT_KEY_NONOPT && !SB_DATA_CAST(data)->path) {
        SB_DATA_CAST(data)->path = strdup(arg);
        return 0;
    }

    return 1;
}

using namespace std;

int main(int argc, char **argv)
{
    struct sparsebundle_data data = {};

    data.logfile = fopen("/tmp/sparesebundlefs.log", "w");
    setvbuf(data.logfile, 0, _IOLBF, 0);

    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    fuse_opt_parse(&args, &data, 0, sparsebundle_opt_proc);

    if (!data.path)
        return sparsebundle_show_usage(argv[0]);

    char *abs_path = realpath(data.path, 0);
    if (!abs_path) {
        perror("Could not resolve absolute path");
        return -1;
    }

    free(data.path);
    data.path = abs_path;

    char *plist_path;
    asprintf(&plist_path, "%s/Info.plist", data.path);

    ifstream plist_file(plist_path);
    stringstream plist_data;
    plist_data << plist_file.rdbuf();

    string key, line;
    while (getline(plist_data, line)) {
        static const char *whitespace_chars = " \n\r\t";
        line.erase(0, line.find_first_not_of(whitespace_chars));
        line.erase(line.find_last_not_of(whitespace_chars) + 1);

        if (line.compare(0, 5, "<key>") == 0) {
            key = line.substr(5, line.length() - 11);
        } else if (!key.empty()) {
            line.erase(0, line.find_first_of('>') + 1);
            line.erase(line.find_first_of('<'));

            if (key == "band-size") {
                data.band_size = atoi(line.c_str());
            } else if (key == "size") {
                data.size = atoi(line.c_str());
            }

            key.clear();
        }
    }

    int ret = fuse_main(args.argc, args.argv, &sparsebundle_filesystem_operations, &data);

    fuse_opt_free_args(&args);
    return ret;
}
<|endoftext|>


<commit_before>#ifndef IOPROCESSES_H
#define IOPROCESSES_H
#include<boost/shared_ptr.hpp>
#include<boost/scoped_ptr.hpp>
#include<vector>
#include<utility>
#include<stack>
#include<string>

#include"processes.hpp"

class PortData; /*abstract port data class*/

class CentralIOToDo;

class IOAction {
public:
	enum ioactions {
		ioaction_read,		/*read some bytes*/
		ioaction_write,		/*write some bytes*/
		ioaction_stdin,		/*get PortData for stdin*/
		ioaction_stdout,	/*get PortData for stdout*/
		ioaction_stderr,	/*get PortData for stderr*/
		ioaction_open,		/*open a filesystem file*/
		ioaction_close,		/*close a PortData*/
		ioaction_server,	/*create a server at port*/
		ioaction_listen,	/*listen on a server PortData*/
		ioaction_sleep,		/*wait a particular amount of time*/
		ioaction_system		/*start another OS process and wait*/
	} action;
	boost::shared_ptr<PortData> port;
	boost::shared_ptr<std::vector<char> > data;
	int num;
	std::string str;
};

/*abstract base*/
class CentralIO {
public:
	/*performs members of the to-do lists that
	can be done now, and returns as soon as those
	are handled
	*/
	virtual void poll(CentralIOToDo) =0;
	/*performs members of the to-do lists
	that can be done now.  If there aren't
	any, waits until at least one can be
	done.
	*/
	virtual void wait(CentralIOToDo) =0;
	/*determine if there are any pending request: returns
	true if no pending requests
	*/
	virtual bool empty(void) =0;
	virtual ~CentralIO();
};

CentralIO* NewCentralIO(void);

class CentralIOProcess;

CentralIOProcess* NewCentralIOProcess(void);

/*PImpl*/
class CentralIOProcess : public ProcessBase {
private:
	boost::scoped_ptr<CentralIO> impl;

	bool waiting;

	typedef std::pair<boost::shared_ptr<Semispace>, Generic* > message;
	typedef std::pair<boost::shared_ptr<ProcessHandle>, message> response;

	/*received queue*/
	std::vector<message> rcv_queue;//protect with lock
	/*to-do list*/
	std::vector<IOAction> todo;
	/*for commission*/
	std::vector<response> snd_queue;

	/*ctor*/
	CentralIOProcess() : waiting(1) {}

public:
	virtual bool receive(boost::shared_ptr<Semispace>, Generic*);
	virtual ProcessStatus run(void);
	virtual ~CentralIOProcess(){}

	CentralIOProcess() : impl(NewCentralIO()), waiting(0) {}

	friend class CentralIOToDo;
	friend CentralIOProcess* NewCentralIOProcess(void);
};

class CentralIOToDo {
private:
	CentralIOProcess* proc;
public:
	explicit CentralIOToDo(CentralIOProcess* p) : proc(p){}
	IOAction get(void);
	void respond(IOAction);
	void error(IOAction, std::string);
};

#endif //IOPROCESSES_H
<commit_msg>ioprocesses: slight rearrangement of declaration<commit_after>#ifndef IOPROCESSES_H
#define IOPROCESSES_H
#include<boost/shared_ptr.hpp>
#include<boost/scoped_ptr.hpp>
#include<vector>
#include<utility>
#include<stack>
#include<string>

#include"processes.hpp"

class PortData; /*abstract port data class*/

class CentralIOToDo;

enum IOActionType {
	ioaction_read,		/*read some bytes*/
	ioaction_write,		/*write some bytes*/
	ioaction_stdin,		/*get PortData for stdin*/
	ioaction_stdout,	/*get PortData for stdout*/
	ioaction_stderr,	/*get PortData for stderr*/
	ioaction_open,		/*open a filesystem file*/
	ioaction_close,		/*close a PortData*/
	ioaction_server,	/*create a server at port*/
	ioaction_listen,	/*listen on a server PortData*/
	ioaction_sleep,		/*wait a particular amount of time*/
	ioaction_system		/*start another OS process and wait*/
};

class IOAction {
public:
	IOActionType action;
	boost::shared_ptr<PortData> port;
	boost::shared_ptr<std::vector<char> > data;
	int num;
	std::string str;
};

/*abstract base*/
class CentralIO {
public:
	/*performs members of the to-do lists that
	can be done now, and returns as soon as those
	are handled
	*/
	virtual void poll(CentralIOToDo) =0;
	/*performs members of the to-do lists
	that can be done now.  If there aren't
	any, waits until at least one can be
	done.
	*/
	virtual void wait(CentralIOToDo) =0;
	/*determine if there are any pending request: returns
	true if no pending requests
	*/
	virtual bool empty(void) =0;
	virtual ~CentralIO();
};

CentralIO* NewCentralIO(void);

class CentralIOProcess;

CentralIOProcess* NewCentralIOProcess(void);

/*PImpl*/
class CentralIOProcess : public ProcessBase {
private:
	boost::scoped_ptr<CentralIO> impl;

	bool waiting;

	typedef std::pair<boost::shared_ptr<Semispace>, Generic* > message;
	typedef std::pair<boost::shared_ptr<ProcessHandle>, message> response;

	/*received queue*/
	std::vector<message> rcv_queue;//protect with lock
	/*to-do list*/
	std::vector<IOAction> todo;
	/*for commission*/
	std::vector<response> snd_queue;

	/*ctor*/
	CentralIOProcess() : waiting(1) {}

public:
	virtual bool receive(boost::shared_ptr<Semispace>, Generic*);
	virtual ProcessStatus run(void);
	virtual ~CentralIOProcess(){}

	CentralIOProcess() : impl(NewCentralIO()), waiting(0) {}

	friend class CentralIOToDo;
	friend CentralIOProcess* NewCentralIOProcess(void);
};

class CentralIOToDo {
private:
	CentralIOProcess* proc;
public:
	explicit CentralIOToDo(CentralIOProcess* p) : proc(p){}
	bool empty(void);
	IOAction get(void);
	void respond(IOAction);
	void error(IOAction, std::string);
};

#endif //IOPROCESSES_H
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <string>
#include <vector>
#include <cmath>
#include <cstring>
using std::string;
using std::vector;
using std::make_pair;
using std::pow;
using std::ceil;

#include <Exceptions.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Kernel.hpp>
#include <Observation.hpp>
using isa::Exceptions::OpenCLError;
using isa::OpenCL::CLData;
using isa::utils::giga;
using isa::utils::toStringValue;
using isa::utils::toString;
using isa::utils::replace;
using isa::OpenCL::Kernel;
using AstroData::Observation;

#ifndef FOLDING_HPP
#define FOLDING_HPP

namespace PulsarSearch {

// OpenCL folding algorithm
template< typename T > class Folding : public Kernel< T > {
public:
	Folding(string name, string dataType);

	void generateCode() throw (OpenCLError);
	void operator()(CLData< T > * input, CLData< T > * output, CLData< unsigned int > * counters) throw (OpenCLError);

	inline void setNrDMsPerBlock(unsigned int DMs);
	inline void setNrPeriodsPerBlock(unsigned int periods);
	inline void setNrBinsPerBlock(unsigned int bins);

	inline void setNrDMsPerThread(unsigned int DMs);
	inline void setNrPeriodsPerThread(unsigned int periods);
	inline void setNrBinsPerThread(unsigned int bins);

	inline void setObservation(Observation< T > * obs);

private:
	unsigned int nrDMsPerBlock;
	unsigned int nrPeriodsPerBlock;
	unsigned int nrBinsPerBlock;
	unsigned int nrDMsPerThread;
	unsigned int nrPeriodsPerThread;
	unsigned int nrBinsPerThread;
	cl::NDRange globalSize;
	cl::NDRange localSize;

	Observation< T > * observation;
};

// Implementation
template< typename T > Folding< T >::Folding(string name, string dataType) : Kernel< T >(name, dataType), nrDMsPerBlock(0), nrPeriodsPerBlock(0), nrBinsPerBlock(0), nrDMsPerThread(0), nrPeriodsPerThread(0), nrBinsPerThread(0), globalSize(cl::NDRange(1, 1, 1)), localSize(cl::NDRange(1, 1, 1)), observation(0) {}

template< typename T > void Folding< T >::generateCode() throw (OpenCLError) {
	// Begin kernel's template
	string nrSamplesPerSecond_s = toStringValue< unsigned int >(observation->getNrSamplesPerSecond());
	string nrPaddedDMs_s  = toStringValue< unsigned int >(observation->getNrPaddedDMs());
	string nrPeriods_s = toStringValue< unsigned int >(observation->getNrPeriods());
	string nrBins_s = toStringValue< unsigned int >(observation->getNrBins());
	string nrDMsPerBlock_s = toStringValue< unsigned int >(nrDMsPerBlock);
	string nrDMsPerThread_s = toStringValue< unsigned int >(nrDMsPerThread);
	string nrPeriodsPerBlock_s = toStringValue< unsigned int >(nrPeriodsPerBlock);
	string nrPeriodsPerThread_s = toStringValue< unsigned int >(nrPeriodsPerThread);
	string nrBinsPerBlock_s = toStringValue< unsigned int >(nrBinsPerBlock);
	string nrBinsPerThread_s = toStringValue< unsigned int >(nrBinsPerThread);

	delete this->code;
	this->code = new string();
	*(this->code) = "__kernel void " + this->name + "(__global const " + this->dataType + " * const restrict samples, __global " + this->dataType + " * const restrict bins, __global unsigned int * const restrict counters) {\n"
	"<%DEFS%>"
	"<%LOADS%>"
	"\n"
	"<%COMPUTE%>"
	"\n"
	"<%STORE%>"
	"}\n";

	string defsDMTemplate = "const unsigned int DM<%DM_NUM%> = (get_group_id(0) * " + nrDMsPerBlock_s + " * " + nrDMsPerThread_s + ") + get_local_id(0) + (<%DM_NUM%> * " + nrDMsPerBlock_s + ");\n";

	string defsPeriodTemplate = "const unsigned int period<%PERIOD_NUM%> = (get_group_id(1) * " + nrPeriodsPerBlock_s + " * " + nrDMsPerThread_s + ") + get_local_id(1) + (<%PERIOD_NUM%> * " + nrPeriodsPerBlock_s + ");\n"
		"const unsigned int period<%PERIOD_NUM%>Value = (period<%PERIOD_NUM%> + 1) * " + nrBins_s + ";\n";

	string defsTemplate = "const unsigned int bin<%BIN_NUM%> = (get_group_id(2) * " + nrBinsPerBlock_s + " * " + nrBinsPerThread_s + ") + get_local_id(2) + (<%BIN_NUM%> * " + nrBinsPerBlock_s + ");\n"
		"unsigned int foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
		+ this->dataType + " foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
		"unsigned int pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n";

	string loadsTemplate = "pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = counters[(bin<%BIN_NUM%> * " + nrPeriods_s + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>];\n";

	string computeTemplate = "unsigned int sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = (bin<%BIN_NUM%> * period<%PERIOD_NUM%>) + bin<%BIN_NUM%> + ((pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> / (period<%PERIOD_NUM%> + 1)) * period<%PERIOD_NUM%>Value) + (pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % (period<%PERIOD_NUM%> + 1));\n"
	"if ( (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % "+ nrSamplesPerSecond_s + ") == 0 ) {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
	"} else {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % "+ nrSamplesPerSecond_s + ") - (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> / "+ nrSamplesPerSecond_s + ");\n"
	"}\n"
	"while ( sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> < " + nrSamplesPerSecond_s + " ) {\n"
	"foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> += samples[(sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>];\n"
	"foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>++;\n"
	"if ( ((foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) % (period<%PERIOD_NUM%> + 1)) == 0 ) {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> += period<%PERIOD_NUM%>Value;\n"
	"} else {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>++;\n"
	"}\n"
	"}\n";

	string storeTemplate = "if ( foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> > 0 ) {\n"
	"const unsigned int outputItem = (bin<%BIN_NUM%> * " + nrPeriods_s + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>;\n"
	"const "+ this->dataType + " pValue = bins[outputItem];\n"
	+ this->dataType + " addedFraction = 0;"
	"addedFraction = convert_float(foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) / (foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>);\n"
	"foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> /= foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>;\n"
	"counters[outputItem] = pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>;\n"
	"bins[outputItem] = (addedFraction * foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) + ((1.0f - addedFraction) * pValue);\n"
	"}\n";
	// End kernel's template

	string * defs = new string();
	string * loads = new string();
	string * computes = new string();
	string * stores = new string();
	for ( unsigned int DM = 0; DM < nrDMsPerThread; DM++ ) {
		string * DM_s = toString< unsigned int >(DM);
		string * temp = 0;

		temp = replace(&defsDMTemplate, "<%DM_NUM%>", *DM_s);
		defs->append(*temp);
		delete temp;

		for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
			string * period_s = toString< unsigned int >(period);
			string * temp = 0;

			temp = replace(&defsPeriodTemplate, "<%PERIOD_NUM%>", *period_s);
			defs->append(*temp);
			delete temp;

			for ( unsigned int bin = 0; bin < nrBinsPerThread; bin++ ) {
				string * bin_s = toString< unsigned int >(bin);
				string * temp = 0;

				temp = replace(&defsTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				defs->append(*temp);
				delete temp;

				temp = replace(&loadsTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				loads->append(*temp);
				delete temp;

				temp = replace(&computeTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				computes->append(*temp);
				delete temp;

				temp = replace(&storeTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				stores->append(*temp);
				delete temp;

				delete bin_s;
			}

			delete period_s;
		}

		delete DM_s;
	}
	this->code = replace(this->code, "<%DEFS%>", *defs, true);
	this->code = replace(this->code, "<%LOADS%>", *loads, true);
	this->code = replace(this->code, "<%COMPUTE%>", *computes, true);
	this->code = replace(this->code, "<%STORE%>", *stores, true);
	delete defs;
	delete computes;
	delete stores;

	globalSize = cl::NDRange(observation->getNrDMs() / nrDMsPerThread, observation->getNrPeriods() / nrPeriodsPerThread, observation->getNrBins() / nrBinsPerThread);
	localSize = cl::NDRange(nrDMsPerBlock, nrPeriodsPerBlock, nrBinsPerBlock);

	this->gflop = giga(static_cast< long long unsigned int >(observation->getNrDMs()) * observation->getNrPeriods() * observation->getNrSamplesPerSecond());

	this->compile();
}

template< typename T > void Folding< T >::operator()(CLData< T > * input, CLData< T > * output, CLData< unsigned int > * counters) throw (OpenCLError) {
	this->setArgument(0, *(input->getDeviceData()));
	this->setArgument(1, *(output->getDeviceData()));
	this->setArgument(2, *(counters->getDeviceData()));

	this->run(globalSize, localSize);
}

template< typename T > inline void Folding< T >::setNrDMsPerBlock(unsigned int DMs) {
	nrDMsPerBlock = DMs;
}

template< typename T > inline void Folding< T >::setNrPeriodsPerBlock(unsigned int periods) {
	nrPeriodsPerBlock = periods;
}

template< typename T > inline void Folding< T >::setNrBinsPerBlock(unsigned int bins) {
	nrBinsPerBlock = bins;
}

template< typename T > inline void Folding< T >::setNrDMsPerThread(unsigned int DMs) {
	nrDMsPerThread = DMs;
}

template< typename T > inline void Folding< T >::setNrPeriodsPerThread(unsigned int periods) {
	nrPeriodsPerThread = periods;
}

template< typename T > inline void Folding< T >::setNrBinsPerThread(unsigned int bins) {
	nrBinsPerThread = bins;
}

template< typename T > inline void Folding< T >::setObservation(Observation< T > * obs) {
	observation = obs;
}

} // PulsarSearch

#endif // FOLDING_HPP
<commit_msg>Still some problems with the code generation.<commit_after>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <string>
#include <vector>
#include <cmath>
#include <cstring>
using std::string;
using std::vector;
using std::make_pair;
using std::pow;
using std::ceil;

#include <Exceptions.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Kernel.hpp>
#include <Observation.hpp>
using isa::Exceptions::OpenCLError;
using isa::OpenCL::CLData;
using isa::utils::giga;
using isa::utils::toStringValue;
using isa::utils::toString;
using isa::utils::replace;
using isa::OpenCL::Kernel;
using AstroData::Observation;

#ifndef FOLDING_HPP
#define FOLDING_HPP

namespace PulsarSearch {

// OpenCL folding algorithm
template< typename T > class Folding : public Kernel< T > {
public:
	Folding(string name, string dataType);

	void generateCode() throw (OpenCLError);
	void operator()(CLData< T > * input, CLData< T > * output, CLData< unsigned int > * counters) throw (OpenCLError);

	inline void setNrDMsPerBlock(unsigned int DMs);
	inline void setNrPeriodsPerBlock(unsigned int periods);
	inline void setNrBinsPerBlock(unsigned int bins);

	inline void setNrDMsPerThread(unsigned int DMs);
	inline void setNrPeriodsPerThread(unsigned int periods);
	inline void setNrBinsPerThread(unsigned int bins);

	inline void setObservation(Observation< T > * obs);

private:
	unsigned int nrDMsPerBlock;
	unsigned int nrPeriodsPerBlock;
	unsigned int nrBinsPerBlock;
	unsigned int nrDMsPerThread;
	unsigned int nrPeriodsPerThread;
	unsigned int nrBinsPerThread;
	cl::NDRange globalSize;
	cl::NDRange localSize;

	Observation< T > * observation;
};

// Implementation
template< typename T > Folding< T >::Folding(string name, string dataType) : Kernel< T >(name, dataType), nrDMsPerBlock(0), nrPeriodsPerBlock(0), nrBinsPerBlock(0), nrDMsPerThread(0), nrPeriodsPerThread(0), nrBinsPerThread(0), globalSize(cl::NDRange(1, 1, 1)), localSize(cl::NDRange(1, 1, 1)), observation(0) {}

template< typename T > void Folding< T >::generateCode() throw (OpenCLError) {
	// Begin kernel's template
	string nrSamplesPerSecond_s = toStringValue< unsigned int >(observation->getNrSamplesPerSecond());
	string nrPaddedDMs_s  = toStringValue< unsigned int >(observation->getNrPaddedDMs());
	string nrPeriods_s = toStringValue< unsigned int >(observation->getNrPeriods());
	string nrBins_s = toStringValue< unsigned int >(observation->getNrBins());
	string nrDMsPerBlock_s = toStringValue< unsigned int >(nrDMsPerBlock);
	string nrDMsPerThread_s = toStringValue< unsigned int >(nrDMsPerThread);
	string nrPeriodsPerBlock_s = toStringValue< unsigned int >(nrPeriodsPerBlock);
	string nrPeriodsPerThread_s = toStringValue< unsigned int >(nrPeriodsPerThread);
	string nrBinsPerBlock_s = toStringValue< unsigned int >(nrBinsPerBlock);
	string nrBinsPerThread_s = toStringValue< unsigned int >(nrBinsPerThread);

	delete this->code;
	this->code = new string();
	*(this->code) = "__kernel void " + this->name + "(__global const " + this->dataType + " * const restrict samples, __global " + this->dataType + " * const restrict bins, __global unsigned int * const restrict counters) {\n"
	"<%DEFS%>"
	"<%LOADS%>"
	"\n"
	"<%COMPUTE%>"
	"\n"
	"<%STORE%>"
	"}\n";

	string defsDMTemplate = "const unsigned int DM<%DM_NUM%> = (get_group_id(0) * " + nrDMsPerBlock_s + " * " + nrDMsPerThread_s + ") + get_local_id(0) + (<%DM_NUM%> * " + nrDMsPerBlock_s + ");\n";

	string defsPeriodTemplate = "const unsigned int period<%PERIOD_NUM%> = (get_group_id(1) * " + nrPeriodsPerBlock_s + " * " + nrDMsPerThread_s + ") + get_local_id(1) + (<%PERIOD_NUM%> * " + nrPeriodsPerBlock_s + ");\n"
		"const unsigned int period<%PERIOD_NUM%>Value = (period<%PERIOD_NUM%> + 1) * " + nrBins_s + ";\n";

	string defsBinTemplate = "const unsigned int bin<%BIN_NUM%> = (get_group_id(2) * " + nrBinsPerBlock_s + " * " + nrBinsPerThread_s + ") + get_local_id(2) + (<%BIN_NUM%> * " + nrBinsPerBlock_s + ");\n";

	string defsTemplate = "unsigned int foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
		+ this->dataType + " foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
		"unsigned int pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n";

	string loadsTemplate = "pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = counters[(bin<%BIN_NUM%> * " + nrPeriods_s + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>];\n";

	string computeTemplate = "unsigned int sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = (bin<%BIN_NUM%> * period<%PERIOD_NUM%>) + bin<%BIN_NUM%> + ((pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> / (period<%PERIOD_NUM%> + 1)) * period<%PERIOD_NUM%>Value) + (pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % (period<%PERIOD_NUM%> + 1));\n"
	"if ( (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % "+ nrSamplesPerSecond_s + ") == 0 ) {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = 0;\n"
	"} else {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> = (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> % "+ nrSamplesPerSecond_s + ") - (sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> / "+ nrSamplesPerSecond_s + ");\n"
	"}\n"
	"while ( sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> < " + nrSamplesPerSecond_s + " ) {\n"
	"foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> += samples[(sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>];\n"
	"foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>++;\n"
	"if ( ((foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) % (period<%PERIOD_NUM%> + 1)) == 0 ) {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> += period<%PERIOD_NUM%>Value;\n"
	"} else {\n"
	"sampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>++;\n"
	"}\n"
	"}\n";

	string storeTemplate = "if ( foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> > 0 ) {\n"
	"const unsigned int outputItem = (bin<%BIN_NUM%> * " + nrPeriods_s + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + DM<%DM_NUM%>;\n"
	"const "+ this->dataType + " pValue = bins[outputItem];\n"
	+ this->dataType + " addedFraction = 0;"
	"addedFraction = convert_float(foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) / (foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>);\n"
	"foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> /= foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>;\n"
	"counters[outputItem] = pCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%> + foldedCounterDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>;\n"
	"bins[outputItem] = (addedFraction * foldedSampleDM<%DM_NUM%>p<%PERIOD_NUM%>b<%BIN_NUM%>) + ((1.0f - addedFraction) * pValue);\n"
	"}\n";
	// End kernel's template

	string * defs = new string();
	string * loads = new string();
	string * computes = new string();
	string * stores = new string();
	for ( unsigned int DM = 0; DM < nrDMsPerThread; DM++ ) {
		string * DM_s = toString< unsigned int >(DM);
		string * temp = 0;

		temp = replace(&defsDMTemplate, "<%DM_NUM%>", *DM_s);
		defs->append(*temp);
		delete temp;

		delete DM_s;
	}
	for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
		string * period_s = toString< unsigned int >(period);
		string * temp = 0;

		temp = replace(&defsPeriodTemplate, "<%PERIOD_NUM%>", *period_s);
		defs->append(*temp);
		delete temp;

		delete period_s;
	}
	for ( unsigned int bin = 0; bin < nrBinsPerThread; bin++ ) {
		string * bin_s = toString< unsigned int >(bin);
		string * temp = 0;

		temp = replace(&defsBinTemplate, "<%BIN_NUM%>", *bin_s);
		defs->append(*temp);
		delete temp;

		delete bin_s;
	}
	for ( unsigned int DM = 0; DM < nrDMsPerThread; DM++ ) {
		string * DM_s = toString< unsigned int >(DM);

		for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
			string * period_s = toString< unsigned int >(period);

			for ( unsigned int bin = 0; bin < nrBinsPerThread; bin++ ) {
				string * bin_s = toString< unsigned int >(bin);
				string * temp = 0;

				temp = replace(&defsTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				defs->append(*temp);
				delete temp;

				temp = replace(&loadsTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				loads->append(*temp);
				delete temp;

				temp = replace(&computeTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				computes->append(*temp);
				delete temp;

				temp = replace(&storeTemplate, "<%BIN_NUM%>", *bin_s);
				temp = replace(temp, "<%PERIOD_NUM%>", *period_s, true);
				temp = replace(temp, "<%DM_NUM%>", *DM_s, true);
				stores->append(*temp);
				delete temp;

				delete bin_s;
			}

			delete period_s;
		}

		delete DM_s;
	}
	this->code = replace(this->code, "<%DEFS%>", *defs, true);
	this->code = replace(this->code, "<%LOADS%>", *loads, true);
	this->code = replace(this->code, "<%COMPUTE%>", *computes, true);
	this->code = replace(this->code, "<%STORE%>", *stores, true);
	delete defs;
	delete computes;
	delete stores;

	globalSize = cl::NDRange(observation->getNrDMs() / nrDMsPerThread, observation->getNrPeriods() / nrPeriodsPerThread, observation->getNrBins() / nrBinsPerThread);
	localSize = cl::NDRange(nrDMsPerBlock, nrPeriodsPerBlock, nrBinsPerBlock);

	this->gflop = giga(static_cast< long long unsigned int >(observation->getNrDMs()) * observation->getNrPeriods() * observation->getNrSamplesPerSecond());

	this->compile();
}

template< typename T > void Folding< T >::operator()(CLData< T > * input, CLData< T > * output, CLData< unsigned int > * counters) throw (OpenCLError) {
	this->setArgument(0, *(input->getDeviceData()));
	this->setArgument(1, *(output->getDeviceData()));
	this->setArgument(2, *(counters->getDeviceData()));

	this->run(globalSize, localSize);
}

template< typename T > inline void Folding< T >::setNrDMsPerBlock(unsigned int DMs) {
	nrDMsPerBlock = DMs;
}

template< typename T > inline void Folding< T >::setNrPeriodsPerBlock(unsigned int periods) {
	nrPeriodsPerBlock = periods;
}

template< typename T > inline void Folding< T >::setNrBinsPerBlock(unsigned int bins) {
	nrBinsPerBlock = bins;
}

template< typename T > inline void Folding< T >::setNrDMsPerThread(unsigned int DMs) {
	nrDMsPerThread = DMs;
}

template< typename T > inline void Folding< T >::setNrPeriodsPerThread(unsigned int periods) {
	nrPeriodsPerThread = periods;
}

template< typename T > inline void Folding< T >::setNrBinsPerThread(unsigned int bins) {
	nrBinsPerThread = bins;
}

template< typename T > inline void Folding< T >::setObservation(Observation< T > * obs) {
	observation = obs;
}

} // PulsarSearch

#endif // FOLDING_HPP
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

// STL
#include <complex>
#include <vector>
#include <array>
#include <algorithm>   //For value_testable
#include <iosfwd>      //For stream support
#include <type_traits> //For static assertions tests
#include <tuple>       //For TMP stuff
#include <thread>

// cpp_utils
#include "cpp_utils/compat.hpp"
#include "cpp_utils/tmp.hpp"
#include "cpp_utils/likely.hpp"
#include "cpp_utils/assert.hpp"
#include "cpp_utils/parallel.hpp"

// Macro to handle noexcept and cpp_assert

namespace etl {

#ifdef NDEBUG
constexpr bool assert_nothrow = true;
#else
#ifdef CPP_UTILS_ASSERT_EXCEPTION
constexpr bool assert_nothrow = false;
#else
constexpr bool assert_nothrow = true;
#endif
#endif

/*!
 * \brief Alignment flag to aligned expressions
 *
 * This can be used to make expressions more clear.
 */
constexpr bool aligned = false;

/*!
 * \brief Alignment flag to unaligned expressions.
 *
 * This can be used to make expressions more clear.
 */
constexpr bool unaligned = false;

} //end of namespace etl
<commit_msg>Add version information to the header<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

// STL
#include <complex>
#include <vector>
#include <array>
#include <algorithm>   //For value_testable
#include <iosfwd>      //For stream support
#include <type_traits> //For static assertions tests
#include <tuple>       //For TMP stuff
#include <thread>

// cpp_utils
#include "cpp_utils/compat.hpp"
#include "cpp_utils/tmp.hpp"
#include "cpp_utils/likely.hpp"
#include "cpp_utils/assert.hpp"
#include "cpp_utils/parallel.hpp"

// Macro to handle noexcept and cpp_assert

namespace etl {

#ifdef NDEBUG
constexpr bool assert_nothrow = true;
#else
#ifdef CPP_UTILS_ASSERT_EXCEPTION
constexpr bool assert_nothrow = false;
#else
constexpr bool assert_nothrow = true;
#endif
#endif

/*!
 * \brief Alignment flag to aligned expressions
 *
 * This can be used to make expressions more clear.
 */
constexpr bool aligned = false;

/*!
 * \brief Alignment flag to unaligned expressions.
 *
 * This can be used to make expressions more clear.
 */
constexpr bool unaligned = false;

/*!
 * \brief The current major version number of the library
 */
constexpr size_t version_major = 1;

/*!
 * \brief The current minor version number of the library
 */
constexpr size_t version_minor = 1;

/*!
 * \brief The current revision version number of the library
 */
constexpr size_t version_revision = 0;

} //end of namespace etl

/*!
 * \brief String representation of the current version of the library.
 */
#define ETL_VERSION_STR "1.0"

/*!
 * \brief The current major version number of the library
 */
#define ETL_VERSION_MAJOR 1

/*!
 * \brief The current minor version number of the library
 */
#define ETL_VERSION_MINOR 1

/*!
 * \brief The current revision version number of the library
 */
#define ETL_VERSION_REVISION 0
<|endoftext|>