<commit_before>#pragma once

#include <string>
#include <cstddef>
#include <cstring>

#include <any.hpp>
#include <reflection_info.hpp>

namespace shadow
{

template <class InfoType, template <class> class... Policies>
class info_type_aggregate
    : public Policies<info_type_aggregate<InfoType, Policies...>>...
{
    template <class Derived>
    friend class name_policy;

    template <class Derived>
    friend class size_policy;

    template <class Derived>
    friend class comparison_policy;

    friend class reflection_manager;

public:
    info_type_aggregate() = default;

    info_type_aggregate(const InfoType& info) : info_ptr_(&info)
    {
    }

    info_type_aggregate* operator->()
    {
        return this;
    }

    const info_type_aggregate* operator->() const
    {
        return this;
    }

private:
    const InfoType* info_ptr_;
};

template <class Derived>
class name_policy
{
public:
    std::string
    name() const
    {
        return std::string(static_cast<const Derived*>(this)->info_ptr_->name);
    }
};

template <class Derived>
class size_policy
{
public:
    std::size_t
    size() const
    {
        return static_cast<const Derived*>(this)->info_ptr_->size;
    }
};

template <class Derived>
class comparison_policy
{
public:
    bool
    operator==(const Derived& other) const
    {
        if(std::strcmp(static_cast<const Derived*>(this)->info_ptr_->name,
                       other.info_ptr_->name) == 0)
        {
            return true;
        }

        return false;
    }

    bool
    operator!=(const Derived& other) const
    {
        return !operator==(other);
    }
};

typedef info_type_aggregate<type_info,
                            name_policy,
                            size_policy,
                            comparison_policy>
    type_tag;

typedef info_type_aggregate<constructor_info> constructor_tag;

typedef info_type_aggregate<conversion_info> conversion_tag;

typedef info_type_aggregate<free_function_info, name_policy> free_function_tag;

class reflection_manager;

class object
{
    friend class reflection_manager;

public:
    object();

    object(any value, const type_info* ti, const reflection_manager* man);

    type_tag type() const;

private:
    any value_;
    const type_info* type_info_;
    const reflection_manager* manager_;
};
}

namespace shadow
{
inline object::object(any value,
                      const type_info* ti,
                      const reflection_manager* man)
    : value_(std::move(value)), type_info_(ti), manager_(man)
{
}

inline type_tag
object::type() const
{
    return type_tag(*type_info_);
}
}
<commit_msg>Add free_function_tag aggregate type. 	modified:   include/api_types.hpp<commit_after>#pragma once

#include <string>
#include <cstddef>
#include <cstring>

#include <any.hpp>
#include <reflection_info.hpp>

namespace shadow
{

template <class InfoType, template <class> class... Policies>
class info_type_aggregate
    : public Policies<info_type_aggregate<InfoType, Policies...>>...
{
    template <class Derived>
    friend class name_policy;

    template <class Derived>
    friend class size_policy;

    template <class Derived>
    friend class comparison_policy;

    friend class reflection_manager;

public:
    info_type_aggregate() = default;

    info_type_aggregate(const InfoType& info) : info_ptr_(&info)
    {
    }

    info_type_aggregate* operator->()
    {
        return this;
    }

    const info_type_aggregate* operator->() const
    {
        return this;
    }

private:
    const InfoType* info_ptr_;
};

template <class Derived>
class name_policy
{
public:
    std::string
    name() const
    {
        return std::string(static_cast<const Derived*>(this)->info_ptr_->name);
    }
};

template <class Derived>
class size_policy
{
public:
    std::size_t
    size() const
    {
        return static_cast<const Derived*>(this)->info_ptr_->size;
    }
};

template <class Derived>
class comparison_policy
{
public:
    bool
    operator==(const Derived& other) const
    {
        if(std::strcmp(static_cast<const Derived*>(this)->info_ptr_->name,
                       other.info_ptr_->name) == 0)
        {
            return true;
        }

        return false;
    }

    bool
    operator!=(const Derived& other) const
    {
        return !operator==(other);
    }
};

typedef info_type_aggregate<type_info,
                            name_policy,
                            size_policy,
                            comparison_policy>
    type_tag;

typedef info_type_aggregate<constructor_info> constructor_tag;

typedef info_type_aggregate<conversion_info> conversion_tag;

typedef info_type_aggregate<free_function_info, name_policy> free_function_tag;

typedef info_type_aggregate<member_function_info, name_policy>
    member_function_tag;

class reflection_manager;

class object
{
    friend class reflection_manager;

public:
    object();

    object(any value, const type_info* ti, const reflection_manager* man);

    type_tag type() const;

private:
    any value_;
    const type_info* type_info_;
    const reflection_manager* manager_;
};
}

namespace shadow
{
inline object::object(any value,
                      const type_info* ti,
                      const reflection_manager* man)
    : value_(std::move(value)), type_info_(ti), manager_(man)
{
}

inline type_tag
object::type() const
{
    return type_tag(*type_info_);
}
}
<|endoftext|>


<commit_before>/*
Hume Library
Copyright (C) 2015 Marshall Clyburn

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
*/

#include "Window.h"

Window::Window() : window(nullptr), renderer(nullptr)
{
}

Window::~Window()
{
    if(window) destroy();
}

void Window::create()
{
    window = SDL_CreateWindow(settings.title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, settings.width, settings.height, 0);
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    assert(window);
    assert(renderer);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

    return;
}

void Window::destroy()
{
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    window = nullptr;
    renderer = nullptr;

    return;
}

void Window::apply(WindowSettings& w)
{
    // update the window based on what's changed
    if(settings.fullscreen != w.fullscreen)
    {
	settings.fullscreen = w.fullscreen;
	if(window)
	{
	    if(settings.fullscreen)
		SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
	    else
		SDL_SetWindowFullscreen(window, 0);
	}
    }
    if(settings.title.compare(w.title) != 0)
    {
	settings.title = w.title;
	if(window) SDL_SetWindowTitle(window, settings.title.c_str());
    }
    if(settings.width != w.width ||
       settings.height != w.height)
    {
	// go ahead and assign the resolution, followed by a resize
	settings.width = w.width;
	settings.height = w.height;
	if(window) SDL_SetWindowSize(window, settings.width, settings.height);
    }

    return;
}

WindowSettings Window::get_settings() const
{
    return settings;
}

SDL_Window* Window::get_window()
{
    return window;
}

SDL_Renderer* Window::get_renderer()
{
    return renderer;
}

void Window::draw(const Blittable* const b, const Properties& p)
{
    SDL_Rect r;
    r.x = p.x;
    r.y = p.y;

    // use the provided width and height if specified
    if(p.w == 0 || p.h == 0)
    {
		r.w = b->get_width();
		r.h = b->get_height();
    }
    else // default width and height
    {
		r.w = p.w;
		r.h = p.h;
    }

    if(p.sw == 0 || p.sh == 0)
		SDL_RenderCopy(renderer, b->get_texture(), nullptr, &r);
    else
    {
		SDL_Rect s;
		s.x = p.sx;
		s.y = p.sy;
		s.w = p.sw;
		s.h = p.sh;
		SDL_RenderCopy(renderer, b->get_texture(), &s, &r);
    }

    return;
}

void Window::present()
{
    SDL_RenderPresent(renderer);
}

void Window::clear()
{
    SDL_RenderClear(renderer);
    return;
}
<commit_msg>Better comments for draw operation.<commit_after>/*
Hume Library
Copyright (C) 2015 Marshall Clyburn

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
*/

#include "Window.h"

Window::Window() : window(nullptr), renderer(nullptr)
{
}

Window::~Window()
{
    if(window) destroy();
}

void Window::create()
{
    window = SDL_CreateWindow(settings.title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, settings.width, settings.height, 0);
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    assert(window);
    assert(renderer);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

    return;
}

void Window::destroy()
{
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    window = nullptr;
    renderer = nullptr;

    return;
}

void Window::apply(WindowSettings& w)
{
    // update the window based on what's changed
    if(settings.fullscreen != w.fullscreen)
    {
	settings.fullscreen = w.fullscreen;
	if(window)
	{
	    if(settings.fullscreen)
		SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
	    else
		SDL_SetWindowFullscreen(window, 0);
	}
    }
    if(settings.title.compare(w.title) != 0)
    {
	settings.title = w.title;
	if(window) SDL_SetWindowTitle(window, settings.title.c_str());
    }
    if(settings.width != w.width ||
       settings.height != w.height)
    {
	// go ahead and assign the resolution, followed by a resize
	settings.width = w.width;
	settings.height = w.height;
	if(window) SDL_SetWindowSize(window, settings.width, settings.height);
    }

    return;
}

WindowSettings Window::get_settings() const
{
    return settings;
}

SDL_Window* Window::get_window()
{
    return window;
}

SDL_Renderer* Window::get_renderer()
{
    return renderer;
}

void Window::draw(const Blittable* const b, const Properties& p)
{
    SDL_Rect r;
    r.x = p.x;
    r.y = p.y;

    // use the default width and height if not specified
    if(p.w == 0 || p.h == 0)
    {
		r.w = b->get_width();
		r.h = b->get_height();
    }
    else // provided width and height
    {
		r.w = p.w;
		r.h = p.h;
    }

    if(p.sw == 0 || p.sh == 0) // use entire blittable
		SDL_RenderCopy(renderer, b->get_texture(), nullptr, &r);
    else // use specified portion
    {
		SDL_Rect s;
		s.x = p.sx;
		s.y = p.sy;
		s.w = p.sw;
		s.h = p.sh;
		SDL_RenderCopy(renderer, b->get_texture(), &s, &r);
    }

    return;
}

void Window::present()
{
    SDL_RenderPresent(renderer);
}

void Window::clear()
{
    SDL_RenderClear(renderer);
    return;
}
<|endoftext|>


<commit_before>/*
Copyright libCellML Contributors

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 "xmldoc.h"

#include <vector>

#include "libcellml/component.h"
#include "libcellml/generator.h"
#include "libcellml/model.h"
#include "libcellml/validator.h"

namespace libcellml{

class GeneratorEquationBinTree;
typedef std::shared_ptr<GeneratorEquationBinTree> GeneratorEquationBinTreePtr;

class GeneratorEquationBinTree
{
public:
    explicit GeneratorEquationBinTree();

    GeneratorEquationBinTreePtr &left();
    GeneratorEquationBinTreePtr &right();

private:
    GeneratorEquationBinTreePtr mLeft;
    GeneratorEquationBinTreePtr mRight;
};

GeneratorEquationBinTree::GeneratorEquationBinTree()
    : mLeft(nullptr)
    , mRight(nullptr)
{
}

GeneratorEquationBinTreePtr &GeneratorEquationBinTree::left()
{
    return mLeft;
}

GeneratorEquationBinTreePtr &GeneratorEquationBinTree::right()
{
    return mRight;
}

class GeneratorEquation;
typedef std::shared_ptr<GeneratorEquation> GeneratorEquationPtr;

class GeneratorEquation
{
public:
    explicit GeneratorEquation();

    GeneratorEquationBinTreePtr &binTree();

private:
    GeneratorEquationBinTreePtr mBinTree;
};

GeneratorEquation::GeneratorEquation()
    : mBinTree(std::make_shared<GeneratorEquationBinTree>())
{
}

GeneratorEquationBinTreePtr &GeneratorEquation::binTree()
{
    return mBinTree;
}

struct GeneratorVariable
{
};

typedef std::shared_ptr<GeneratorVariable> GeneratorVariablePtr;

struct Generator::GeneratorImpl
{
    bool mWithNames;

    std::vector<GeneratorVariablePtr> mStates;
    std::vector<GeneratorVariablePtr> mVariables;

    size_t mathmlChildCount(const XmlNodePtr &node) const;
    XmlNodePtr mathmlChildNode(const XmlNodePtr &node, int index) const;

    void processNode(const XmlNodePtr &node);
};

size_t Generator::GeneratorImpl::mathmlChildCount(const XmlNodePtr &node) const
{
    // Return the number of child elements, in the MathML namespace, for the
    // given node

    size_t res = 0;
    XmlNodePtr childNode = node->getFirstChild();

    while (childNode != nullptr) {
        if (childNode->isMathmlElement()) {
            ++res;
        }

        childNode = childNode->getNext();
    }

    return res;
}

XmlNodePtr Generator::GeneratorImpl::mathmlChildNode(const XmlNodePtr &node, int index) const
{
    // Return the nth child element of the given node, skipping anything that is
    // not int he MathML namespace

    // Retrieve the first MathML node, if it exists

    XmlNodePtr res = node->getFirstChild();

    while (res && !res->isMathmlElement()) {
        res = res->getNext();
    }

    // Retrieve the nth MathML element, if it exists

    int nodeIndex = 0;

    while (res && (nodeIndex != index)) {
        while (res && !res->isMathmlElement()) {
            res = res->getNext();
        }

        ++nodeIndex;
    }

    return res;
}

void Generator::GeneratorImpl::processNode(const XmlNodePtr &node)
{
(void) node;

//TODO
}

Generator::Generator()
    : mPimpl(new GeneratorImpl())
{
}

Generator::~Generator()
{
    delete mPimpl;
}

Generator::Generator(const Generator &rhs)
    : Logger(rhs)
    , mPimpl(new GeneratorImpl())
{
    mPimpl->mStates = rhs.mPimpl->mStates;
    mPimpl->mVariables = rhs.mPimpl->mVariables;
}

Generator::Generator(Generator &&rhs)
    : Logger(std::move(rhs))
    , mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

Generator& Generator::operator=(Generator rhs)
{
    Logger::operator =(rhs);
    rhs.swap(*this);
    return *this;
}

void Generator::swap(Generator &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void Generator::processModel(const ModelPtr &model)
{
    // Make sure that the model is valid before processing it

/*TODO: reenable the validation once it is known to work fine...
    libcellml::Validator validator;

    validator.validateModel(model);

    if (validator.errorCount() > 0) {
        // The model is not valid, so retrieve the validation errors and keep a
        // copy of them

        for (size_t i = 0; i < validator.errorCount(); ++i)
            addError(validator.getError(i));

        return;
    }
*/

    // Determine the order in which equations should be executed by processing
    // each of the components in the given model

    for (size_t i = 0; i < model->componentCount(); ++i) {
        // Retrieve the math string associated with the given component and
        // process it, one equation at a time
        // Note: at this stage, we know the model is valid, so no point in
        //       revalidating the math string...

        ComponentPtr component = model->getComponent(i);
        XmlDocPtr xmlDoc = std::make_shared<XmlDoc>();
        std::string math = component->getMath();

        xmlDoc->parse(math);

        XmlNodePtr mathNode = xmlDoc->getRootNode();

        for (XmlNodePtr node = mathNode->getFirstChild();
             node != nullptr; node = node->getNext()) {
            mPimpl->processNode(node);
        }
    }
}

void Generator::setWithNames(bool withNames)
{
    mPimpl->mWithNames = withNames;
}

size_t Generator::stateCount() const
{
    return mPimpl->mStates.size();
}

size_t Generator::rateCount() const
{
    return stateCount();
}

size_t Generator::variableCount() const
{
    return mPimpl->mVariables.size();
}

std::string Generator::initializeVariables() const
{
    return "";
}

std::string Generator::computeConstantEquations() const
{
    return "";
}

std::string Generator::computeRateEquations() const
{
    return "";
}

std::string Generator::computeAlgebraicEquations() const
{
    return "";
}

}
<commit_msg>Generator::GeneratorImpl: added methods to count the number of MathML nodes and retrieve the MathML node at index n.<commit_after>/*
Copyright libCellML Contributors

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 "xmldoc.h"

#include <vector>

#include "libcellml/component.h"
#include "libcellml/generator.h"
#include "libcellml/model.h"
#include "libcellml/validator.h"

namespace libcellml{

class GeneratorEquationBinTree;
typedef std::shared_ptr<GeneratorEquationBinTree> GeneratorEquationBinTreePtr;

class GeneratorEquationBinTree
{
public:
    explicit GeneratorEquationBinTree();

    GeneratorEquationBinTreePtr &left();
    GeneratorEquationBinTreePtr &right();

private:
    GeneratorEquationBinTreePtr mLeft;
    GeneratorEquationBinTreePtr mRight;
};

GeneratorEquationBinTree::GeneratorEquationBinTree()
    : mLeft(nullptr)
    , mRight(nullptr)
{
}

GeneratorEquationBinTreePtr &GeneratorEquationBinTree::left()
{
    return mLeft;
}

GeneratorEquationBinTreePtr &GeneratorEquationBinTree::right()
{
    return mRight;
}

class GeneratorEquation;
typedef std::shared_ptr<GeneratorEquation> GeneratorEquationPtr;

class GeneratorEquation
{
public:
    explicit GeneratorEquation();

    GeneratorEquationBinTreePtr &binTree();

private:
    GeneratorEquationBinTreePtr mBinTree;
};

GeneratorEquation::GeneratorEquation()
    : mBinTree(std::make_shared<GeneratorEquationBinTree>())
{
}

GeneratorEquationBinTreePtr &GeneratorEquation::binTree()
{
    return mBinTree;
}

struct GeneratorVariable
{
};

typedef std::shared_ptr<GeneratorVariable> GeneratorVariablePtr;

struct Generator::GeneratorImpl
{
    bool mWithNames;

    std::vector<GeneratorVariablePtr> mStates;
    std::vector<GeneratorVariablePtr> mVariables;

    size_t mathmlChildCount(const XmlNodePtr &node) const;
    XmlNodePtr mathmlChildNode(const XmlNodePtr &node, size_t index) const;

    void processNode(const XmlNodePtr &node);
};

size_t Generator::GeneratorImpl::mathmlChildCount(const XmlNodePtr &node) const
{
    // Return the number of child elements, in the MathML namespace, for the
    // given node

    XmlNodePtr childNode = node->getFirstChild();
    size_t res = (childNode->isMathmlElement())?1:0;

    while (childNode != nullptr) {
        childNode = childNode->getNext();

        if (childNode && childNode->isMathmlElement()) {
            ++res;
        }
    }

    return res;
}

XmlNodePtr Generator::GeneratorImpl::mathmlChildNode(const XmlNodePtr &node, size_t index) const
{
    // Return the nth child element of the given node, skipping anything that is
    // not int he MathML namespace

    XmlNodePtr res = node->getFirstChild();
    size_t childNodeIndex = (res->isMathmlElement())?0:SIZE_T_MAX;

    while ((res != nullptr) && (childNodeIndex != index)) {
        res = res->getNext();

        if (res && res->isMathmlElement()) {
            ++childNodeIndex;
        }
    }

    return res;
}

void Generator::GeneratorImpl::processNode(const XmlNodePtr &node)
{
(void) node;

//TODO
}

Generator::Generator()
    : mPimpl(new GeneratorImpl())
{
}

Generator::~Generator()
{
    delete mPimpl;
}

Generator::Generator(const Generator &rhs)
    : Logger(rhs)
    , mPimpl(new GeneratorImpl())
{
    mPimpl->mStates = rhs.mPimpl->mStates;
    mPimpl->mVariables = rhs.mPimpl->mVariables;
}

Generator::Generator(Generator &&rhs)
    : Logger(std::move(rhs))
    , mPimpl(rhs.mPimpl)
{
    rhs.mPimpl = nullptr;
}

Generator& Generator::operator=(Generator rhs)
{
    Logger::operator =(rhs);
    rhs.swap(*this);
    return *this;
}

void Generator::swap(Generator &rhs)
{
    std::swap(this->mPimpl, rhs.mPimpl);
}

void Generator::processModel(const ModelPtr &model)
{
    // Make sure that the model is valid before processing it

/*TODO: reenable the validation once it is known to work fine...
    libcellml::Validator validator;

    validator.validateModel(model);

    if (validator.errorCount() > 0) {
        // The model is not valid, so retrieve the validation errors and keep a
        // copy of them

        for (size_t i = 0; i < validator.errorCount(); ++i)
            addError(validator.getError(i));

        return;
    }
*/

    // Determine the order in which equations should be executed by processing
    // each of the components in the given model

    for (size_t i = 0; i < model->componentCount(); ++i) {
        // Retrieve the math string associated with the given component and
        // process it, one equation at a time
        // Note: at this stage, we know the model is valid, so no point in
        //       revalidating the math string...

        ComponentPtr component = model->getComponent(i);
        XmlDocPtr xmlDoc = std::make_shared<XmlDoc>();
        std::string math = component->getMath();

        xmlDoc->parse(math);

        XmlNodePtr mathNode = xmlDoc->getRootNode();

        for (XmlNodePtr node = mathNode->getFirstChild();
             node != nullptr; node = node->getNext()) {
            mPimpl->processNode(node);
        }
    }
}

void Generator::setWithNames(bool withNames)
{
    mPimpl->mWithNames = withNames;
}

size_t Generator::stateCount() const
{
    return mPimpl->mStates.size();
}

size_t Generator::rateCount() const
{
    return stateCount();
}

size_t Generator::variableCount() const
{
    return mPimpl->mVariables.size();
}

std::string Generator::initializeVariables() const
{
    return "";
}

std::string Generator::computeConstantEquations() const
{
    return "";
}

std::string Generator::computeRateEquations() const
{
    return "";
}

std::string Generator::computeAlgebraicEquations() const
{
    return "";
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Andreas Sandberg
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef DCXX_TYPES_HH
#define DCXX_TYPES_HH

#include <cmath>
#include <dcxx/utils.hh>

DCXX_BEGIN_NS_DC

/** One foot in meter */
#define DCXX_FOOT 0.3048

struct Duration {
    Duration(double val)
	: val(val) {}

    static Duration seconds(double val) {
	return Duration(val);
    }

    double seconds() const {
	return val;
    }

    static Duration minutes(double val) {
	return Duration(val * 60);
    }

    double minutes() const {
	return val / 60;
    }

    static Duration hours(double val) {
	return Duration(val * 60 * 60);
    }

    double hours() const {
	return val / 60 / 60;
    }

    operator double() { return val; }

    /** Duration in seconds */
    double val;
};

struct Length {
    Length(double val)
	: val(val) {}

    static Length feet(double val) {
	return Length(DCXX_FOOT * val);
    }

    double feet() const {
	return val / DCXX_FOOT;
    }

    operator double() { return val; }

    /** Length, always in meter */
    double val;
};

DCXX_END_NS

#endif
<commit_msg>Add accessor and factory functions to explicitly create lengths in metres<commit_after>/*
 * Copyright (c) 2011, Andreas Sandberg
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef DCXX_TYPES_HH
#define DCXX_TYPES_HH

#include <cmath>
#include <dcxx/utils.hh>

DCXX_BEGIN_NS_DC

/** One foot in meter */
#define DCXX_FOOT 0.3048

struct Duration {
    Duration(double val)
	: val(val) {}

    static Duration seconds(double val) {
	return Duration(val);
    }

    double seconds() const {
	return val;
    }

    static Duration minutes(double val) {
	return Duration(val * 60);
    }

    double minutes() const {
	return val / 60;
    }

    static Duration hours(double val) {
	return Duration(val * 60 * 60);
    }

    double hours() const {
	return val / 60 / 60;
    }

    operator double() { return val; }

    /** Duration in seconds */
    double val;
};

struct Length {
    Length(double val)
	: val(val) {}

    static Length metre(double val) {
	return Length(val);
    }

    double metre() const {
	return val;
    }

    static Length feet(double val) {
	return Length(DCXX_FOOT * val);
    }

    double feet() const {
	return val / DCXX_FOOT;
    }

    operator double() { return val; }

    /** Length, always in meter */
    double val;
};

DCXX_END_NS

#endif
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Karoliina T. Salminen <karoliina.t.salminen@nokia.com>
**
** This file is part of duicontrolpanel.
**
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */

#include "duicontrolpanelservice.h"
#include "pagefactory.h"
#include "dcpappletmanager.h"

#include "duicontrolpanelifadaptor.h"
#include "duicontrolpanelif.h"

#include <MApplicationIfAdaptor>
#include <QtDebug>
#include <MApplication>
#include <MApplicationWindow>
#include <QDBusServiceWatcher>
#include <dcpappletdb.h>

static const char* serviceName = "com.nokia.DuiControlPanel";
static const char* serviceNameAppl = "com.nokia.DcpAppletLauncher";
bool DuiControlPanelService::isStartedByServiceFw = false;

#include "dcpdebug.h"

DuiControlPanelService::DuiControlPanelService ():
    MApplicationService (serviceName),
    m_StartPage (new PageHandle()),
    m_IsRegistered (false)
{
    // by default open the main page:
    if (! isStartedByServiceFw) {
        mainPage();
    }
}

void
DuiControlPanelService::launch ()
{
//    MApplicationService::launch ();

    /* this method not supposed to change the current page,
     * so we only setup a default if there is not any yet
     */

#ifdef NO_PAGE_DROPPING
    MApplicationWindow *win = MApplication::activeApplicationWindow();
    if ((m_StartPage && m_StartPage->id == PageHandle::NOPAGE) ||
        (!m_StartPage && win && !win->currentPage()))
#endif
    {
        mainPage();
    }
}

void
DuiControlPanelService::launch (const QStringList &parameters)
{
    if (parameters.isEmpty()) {
        launch();
    } else {
        appletPage (parameters.at(0));
    }
}

bool
DuiControlPanelService::registerService ()
{
    if (m_IsRegistered) return true;

    // memory owned by QDBusAbstractAdaptor instance and must be on the heap
    new DuiControlPanelIfAdaptor(this);
    new MApplicationIfAdaptor(this);

    QDBusConnection connection = QDBusConnection::sessionBus();

    bool ret = connection.registerService(serviceName);
    if (ret) {
        ret = connection.registerObject("/", this)
              && connection.registerObject("/org/maemo/m", this);

        if (!ret) {
            qWarning ("Error while registering the service object");
        }
    } else {
        qWarning ("Error while registering the service name");
    }

    if (!ret) {
        handleServiceRegistrationFailure();
    }

    m_IsRegistered = ret;
    return ret;
}

bool
DuiControlPanelService::appletPage (const QString& appletName)
{
    MApplicationWindow* win = MApplication::activeApplicationWindow();
    if (!PageFactory::isInProcessApplets()) {
        // if we have no page yet and this is the first applet start,
        // then we run it inprocess and behave like an appletlauncher
        if (isStartedByServiceFw && (!win || !win->currentPage()))
        {
            bool success = unregisterService ();
            dcp_failfunc_unless (success, false);
            receiveCloseSignal ();
            DcpAppletManager *mng = DcpAppletManager::instance();
            mng->loadMetadata ();
            mng->applet (appletName);
        } else {
            // if we already have a page, then we start another instance,
            // and exit from mainloop:
            unregisterService ();
            DuiControlPanelIf iface;
            dcp_failfunc_unless (iface.isValid(), false);
            iface.appletPage (appletName);
            qApp->exit ();
            return true;
        }
    }

    PageHandle handle (PageHandle::APPLET, appletName, -1, true);
    sheduleStart(handle);

    // TODO this hack prevents a servicefw issue, that the app does not get the
    // first query
    // Result means nothing...
    return true;
}

// this function makes us close if the main process arrives:
void
DuiControlPanelService::receiveCloseSignal ()
{
    QDBusServiceWatcher* watcher =
        new QDBusServiceWatcher (serviceName,
                QDBusConnection::sessionBus(),
                QDBusServiceWatcher::WatchForRegistration, this);
    connect (watcher, SIGNAL (serviceRegistered(QString)),
             qApp, SLOT (quit()));
}

void
DuiControlPanelService::receivePreloadSignal ()
{
    QDBusServiceWatcher* watcher =
        new QDBusServiceWatcher (serviceNameAppl,
                QDBusConnection::sessionBus(),
                QDBusServiceWatcher::WatchForUnregistration, this);
    connect (watcher, SIGNAL (serviceUnregistered(QString)),
             this, SLOT (preloadAppletLauncher()));
}

void
DuiControlPanelService::preloadAppletLauncher ()
{
    PageFactory* pf = PageFactory::instance();
    dcp_failfunc_unless (pf);
    QTimer::singleShot (1000, pf, SLOT(preloadAppletLauncher()));
}

// FIXME XXX we should consider a common base class with DcpAppletLauncherService
bool DuiControlPanelService::unregisterService ()
{
    if (!m_IsRegistered) return true;
    QDBusConnection connection = QDBusConnection::sessionBus();

    connection.unregisterObject("/");
    connection.unregisterObject("/org/maemo/m");
    bool ret = connection.unregisterService (serviceName);
    if (!ret) {
        QDBusError error = connection.lastError();
        qWarning ("Unregistering the service failed (%s): %s",
                qPrintable (error.name()), qPrintable (error.message()));
    }

    m_IsRegistered = !ret;
    return ret;
}

bool
DuiControlPanelService::appletPage (const QStringList& params)
{
    if (params.isEmpty()) return false;

    // TODO we could add the other parameters to the applet
    QString appletName = params.at(0);
    return appletPage (appletName);
}

/* Starts the page through PageFactory */
void DuiControlPanelService::startPageForReal(const PageHandle &handle)
{
    PageFactory* pf = PageFactory::instance();

    // true means that it drops all the other pages
    bool success = pf->changePage(handle, true);

    if (success) {
        pf->raiseMainWindow ();
    } else {
        qWarning ("Failed to switch page (wrong page id?)");
    }
}

/* Either starts the page or shedules starting it if the window is not yet
 * created. */
void
DuiControlPanelService::sheduleStart (
                const PageHandle &handle)
{
    /* start contains the page to start when the window has appeared.
     * After the window is already created, it is null */
    if (m_StartPage == 0) {
        startPageForReal(handle);
    } else {
        *m_StartPage = handle;
    }
}

void
DuiControlPanelService::categoryPage (const QString& category)
{
    PageHandle handle (PageHandle::APPLETCATEGORY, category, -1, true);
    sheduleStart(handle);
}

void
DuiControlPanelService::mainPage()
{
    PageHandle handle (PageHandle::MAIN);
    sheduleStart(handle);
}

// this method gets called after mainwindow has been created,
// so after it has been called, the pages can be created for real
void
DuiControlPanelService::createStartPage()
{
    // createStartPage should not be called twice
    dcp_failfunc_unless (m_StartPage);

    PageHandle* handle = m_StartPage;
    m_StartPage = 0;

    // if started through servicefw we can end up not receiving the
    // servicefw call at this point, so taking no action yet
    if (handle->id != PageHandle::NOPAGE) {
        startPageForReal (*handle);
    }

    // From now on, pagefactory will be able to notify the applets running
    // in separate process to close down through this, but only if we
    // are the main process (not an appletlauncher)
    if (m_IsRegistered) {
        PageFactory* pf = PageFactory::instance();
        connect (pf, SIGNAL (resetAppletLauncherProcesses()),
                 this, SIGNAL (closeAppletLaunchers()));

        // applet launcher preloading:
        receivePreloadSignal();
    }

    delete handle;
}

<commit_msg>DuiControlPanelService::launch(params) does not handle applet popup<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Karoliina T. Salminen <karoliina.t.salminen@nokia.com>
**
** This file is part of duicontrolpanel.
**
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */

#include "duicontrolpanelservice.h"
#include "pagefactory.h"
#include "dcpappletmanager.h"

#include "duicontrolpanelifadaptor.h"
#include "duicontrolpanelif.h"

#include <MApplicationIfAdaptor>
#include <QtDebug>
#include <MApplication>
#include <MApplicationWindow>
#include <QDBusServiceWatcher>
#include <dcpappletdb.h>

static const char* serviceName = "com.nokia.DuiControlPanel";
static const char* serviceNameAppl = "com.nokia.DcpAppletLauncher";
bool DuiControlPanelService::isStartedByServiceFw = false;

#include "dcpdebug.h"

DuiControlPanelService::DuiControlPanelService ():
    MApplicationService (serviceName),
    m_StartPage (new PageHandle()),
    m_IsRegistered (false)
{
    // by default open the main page:
    if (! isStartedByServiceFw) {
        mainPage();
    }
}

void
DuiControlPanelService::launch ()
{
//    MApplicationService::launch ();

    /* this method not supposed to change the current page,
     * so we only setup a default if there is not any yet
     */

#ifdef NO_PAGE_DROPPING
    MApplicationWindow *win = MApplication::activeApplicationWindow();
    if ((m_StartPage && m_StartPage->id == PageHandle::NOPAGE) ||
        (!m_StartPage && win && !win->currentPage()))
#endif
    {
        mainPage();
    }
}

void
DuiControlPanelService::launch (const QStringList &parameters)
{
    Q_UNUSED (parameters);
    launch();
}

bool
DuiControlPanelService::registerService ()
{
    if (m_IsRegistered) return true;

    // memory owned by QDBusAbstractAdaptor instance and must be on the heap
    new DuiControlPanelIfAdaptor(this);
    new MApplicationIfAdaptor(this);

    QDBusConnection connection = QDBusConnection::sessionBus();

    bool ret = connection.registerService(serviceName);
    if (ret) {
        ret = connection.registerObject("/", this)
              && connection.registerObject("/org/maemo/m", this);

        if (!ret) {
            qWarning ("Error while registering the service object");
        }
    } else {
        qWarning ("Error while registering the service name");
    }

    if (!ret) {
        handleServiceRegistrationFailure();
    }

    m_IsRegistered = ret;
    return ret;
}

bool
DuiControlPanelService::appletPage (const QString& appletName)
{
    MApplicationWindow* win = MApplication::activeApplicationWindow();
    if (!PageFactory::isInProcessApplets()) {
        // if we have no page yet and this is the first applet start,
        // then we run it inprocess and behave like an appletlauncher
        if (isStartedByServiceFw && (!win || !win->currentPage()))
        {
            bool success = unregisterService ();
            dcp_failfunc_unless (success, false);
            receiveCloseSignal ();
            DcpAppletManager *mng = DcpAppletManager::instance();
            mng->loadMetadata ();
            mng->applet (appletName);
        } else {
            // if we already have a page, then we start another instance,
            // and exit from mainloop:
            unregisterService ();
            DuiControlPanelIf iface;
            dcp_failfunc_unless (iface.isValid(), false);
            iface.appletPage (appletName);
            qApp->exit ();
            return true;
        }
    }

    PageHandle handle (PageHandle::APPLET, appletName, -1, true);
    sheduleStart(handle);

    // TODO this hack prevents a servicefw issue, that the app does not get the
    // first query
    // Result means nothing...
    return true;
}

// this function makes us close if the main process arrives:
void
DuiControlPanelService::receiveCloseSignal ()
{
    QDBusServiceWatcher* watcher =
        new QDBusServiceWatcher (serviceName,
                QDBusConnection::sessionBus(),
                QDBusServiceWatcher::WatchForRegistration, this);
    connect (watcher, SIGNAL (serviceRegistered(QString)),
             qApp, SLOT (quit()));
}

void
DuiControlPanelService::receivePreloadSignal ()
{
    QDBusServiceWatcher* watcher =
        new QDBusServiceWatcher (serviceNameAppl,
                QDBusConnection::sessionBus(),
                QDBusServiceWatcher::WatchForUnregistration, this);
    connect (watcher, SIGNAL (serviceUnregistered(QString)),
             this, SLOT (preloadAppletLauncher()));
}

void
DuiControlPanelService::preloadAppletLauncher ()
{
    PageFactory* pf = PageFactory::instance();
    dcp_failfunc_unless (pf);
    QTimer::singleShot (1000, pf, SLOT(preloadAppletLauncher()));
}

// FIXME XXX we should consider a common base class with DcpAppletLauncherService
bool DuiControlPanelService::unregisterService ()
{
    if (!m_IsRegistered) return true;
    QDBusConnection connection = QDBusConnection::sessionBus();

    connection.unregisterObject("/");
    connection.unregisterObject("/org/maemo/m");
    bool ret = connection.unregisterService (serviceName);
    if (!ret) {
        QDBusError error = connection.lastError();
        qWarning ("Unregistering the service failed (%s): %s",
                qPrintable (error.name()), qPrintable (error.message()));
    }

    m_IsRegistered = !ret;
    return ret;
}

bool
DuiControlPanelService::appletPage (const QStringList& params)
{
    if (params.isEmpty()) return false;

    // TODO we could add the other parameters to the applet
    QString appletName = params.at(0);
    return appletPage (appletName);
}

/* Starts the page through PageFactory */
void DuiControlPanelService::startPageForReal(const PageHandle &handle)
{
    PageFactory* pf = PageFactory::instance();

    // true means that it drops all the other pages
    bool success = pf->changePage(handle, true);

    if (success) {
        pf->raiseMainWindow ();
    } else {
        qWarning ("Failed to switch page (wrong page id?)");
    }
}

/* Either starts the page or shedules starting it if the window is not yet
 * created. */
void
DuiControlPanelService::sheduleStart (
                const PageHandle &handle)
{
    /* start contains the page to start when the window has appeared.
     * After the window is already created, it is null */
    if (m_StartPage == 0) {
        startPageForReal(handle);
    } else {
        *m_StartPage = handle;
    }
}

void
DuiControlPanelService::categoryPage (const QString& category)
{
    PageHandle handle (PageHandle::APPLETCATEGORY, category, -1, true);
    sheduleStart(handle);
}

void
DuiControlPanelService::mainPage()
{
    PageHandle handle (PageHandle::MAIN);
    sheduleStart(handle);
}

// this method gets called after mainwindow has been created,
// so after it has been called, the pages can be created for real
void
DuiControlPanelService::createStartPage()
{
    // createStartPage should not be called twice
    dcp_failfunc_unless (m_StartPage);

    PageHandle* handle = m_StartPage;
    m_StartPage = 0;

    // if started through servicefw we can end up not receiving the
    // servicefw call at this point, so taking no action yet
    if (handle->id != PageHandle::NOPAGE) {
        startPageForReal (*handle);
    }

    // From now on, pagefactory will be able to notify the applets running
    // in separate process to close down through this, but only if we
    // are the main process (not an appletlauncher)
    if (m_IsRegistered) {
        PageFactory* pf = PageFactory::instance();
        connect (pf, SIGNAL (resetAppletLauncherProcesses()),
                 this, SIGNAL (closeAppletLaunchers()));

        // applet launcher preloading:
        receivePreloadSignal();
    }

    delete handle;
}

<|endoftext|>


<commit_before>/*
 * SchemeEval.c
 *
 * Simple scheme evaluator
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include "SchemeEval.h"

#include <libguile.h>
#include <libguile/backtrace.h>
#include <libguile/debug.h>
#include <libguile/lang.h>

#include "platform.h"
#include "SchemeSmob.h"

using namespace opencog;

bool SchemeEval::is_inited = false;

SchemeEval::SchemeEval(void)
{
	if (!is_inited)
	{
		is_inited = true;
		scm_init_guile();
		// DO NOT call scm_init_debug(), this will mess up debugging!
		// scm_init_debug();
		// scm_init_backtrace();
		// scm_init_strports(); // is this really needed ?
		SchemeSmob::init();
	}

	outport = scm_open_output_string();
	scm_set_current_output_port(outport);

	pending_input = false;
	caught_error = false;
	input_line = "";
}

/* ============================================================== */

std::string SchemeEval::prt(SCM node)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, node))
	{
		return SchemeSmob::handle_to_string(node);
	}

	else if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, node))
	{
		return SchemeSmob::misc_to_string(node);
	}

	else if (scm_is_eq(node, SCM_UNSPECIFIED))
	{
		return "";
	}
#if CUSTOM_PRINTING_WHY_DO_WE_HAVE_THIS_DELETE_ME
	else if (scm_is_pair(node))
	{
		std::string str = "(";
      SCM node_list = node;
		const char * sp = "";
      do
      {
			str += sp;
			sp = " ";
         node = SCM_CAR (node_list);
         str += prt (node);
         node_list = SCM_CDR (node_list);
      }
      while (scm_is_pair(node_list));

		// Print the rest -- the CDR part
		if (!scm_is_null(node_list))
		{
			str += " . ";
			str += prt (node_list);
		}
		str += ")";
		return str;
   }
	else if (scm_is_true(scm_symbol_p(node)))
	{
		node = scm_symbol_to_string(node);
		char * str = scm_to_locale_string(node);
		// std::string rv = "'";  // print the symbol escape
		std::string rv = "";      // err .. don't print it
		rv += str;
		free(str);
		return rv;
	}
	else if (scm_is_true(scm_string_p(node)))
	{
		char * str = scm_to_locale_string(node);
		std::string rv = "\"";
		rv += str;
		rv += "\"";
		free(str);
		return rv;
	}
	else if (scm_is_number(node))
	{
		#define NUMBUFSZ 60
		char buff[NUMBUFSZ];
		if (scm_is_signed_integer(node, INT_MIN, INT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%ld", (long) scm_to_long(node));
		}
		else if (scm_is_unsigned_integer(node, 0, UINT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%lu", (unsigned long) scm_to_ulong(node));
		}
		else if (scm_is_real(node))
		{
			snprintf (buff, NUMBUFSZ, "%g", scm_to_double(node));
		}
		else if (scm_is_complex(node))
		{
			snprintf (buff, NUMBUFSZ, "%g +i %g",
				scm_c_real_part(node),
				scm_c_imag_part(node));
		}
		else if (scm_is_rational(node))
		{
			std::string rv;
			rv = prt(scm_numerator(node));
			rv += "/";
			rv += prt(scm_denominator(node));
			return rv;
		}
		return buff;
	}
	else if (scm_is_true(scm_char_p(node)))
	{
		std::string rv;
		rv = (char) scm_to_char(node);
		return rv;
	}
	else if (scm_is_true(scm_boolean_p(node)))
	{
		if (scm_to_bool(node)) return "#t";
		return "#f";
	}
	else if (SCM_NULL_OR_NIL_P(node))
	{
		// scm_is_null(x) is true when x is SCM_EOL
		// SCM_NILP(x) is true when x is SCM_ELISP_NIL
		return "()";
	}
	else if (scm_is_eq(node, SCM_UNDEFINED))
	{
		return "undefined";
	}
	else if (scm_is_eq(node, SCM_EOF_VAL))
	{
		return "eof";
	}
#endif
	else
	{
		// Let SCM display do the rest of the work.
		SCM port = scm_open_output_string();
		scm_display (node, port);
		SCM rc = scm_get_output_string(port);
		char * str = scm_to_locale_string(rc);
		std::string rv = str;
		free(str);
		scm_close_port(port);
		return rv;
	}

	return "";
}

/* ============================================================== */

SCM SchemeEval::preunwind_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->preunwind_handler(tag, throw_args);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->catch_handler(tag, throw_args);
}

SCM SchemeEval::preunwind_handler (SCM tag, SCM throw_args)
{
	// We can only record the stack before it is unwound.
	// The normal catch handler body runs only *after* the stack
	// has been unwound.
	captured_stack = scm_make_stack (SCM_BOOL_T, SCM_EOL);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler (SCM tag, SCM throw_args)
{
	// Check for read error. If a read error, then wait for user to correct it.
	SCM re = scm_symbol_to_string(tag);
	char * restr = scm_to_locale_string(re);
	pending_input = false;
	if (0 == strcmp(restr, "read-error"))
	{
		pending_input = true;
		free(restr);
		return SCM_EOL;
	}

	// If its not a read error, then its a regular error; report it.
	caught_error = true;

	/* get string port into which we write the error message and stack. */
	error_string_port = scm_open_output_string();
	SCM port = error_string_port;

	if (scm_is_true(scm_list_p(throw_args)) && (scm_ilength(throw_args) >= 1))
	{
		long nargs = scm_ilength(throw_args);
		SCM subr    = SCM_CAR (throw_args);
		SCM message = SCM_EOL;
		if (nargs >= 2)
			message = SCM_CADR (throw_args);
		SCM parts   = SCM_EOL;
		if (nargs >= 3)
			parts   = SCM_CADDR (throw_args);
		SCM rest    = SCM_EOL;
		if (nargs >= 4)
			rest    = SCM_CADDDR (throw_args);

		if (scm_is_true (captured_stack))
		{
			SCM highlights;

			if (scm_is_eq (tag, scm_arg_type_key) ||
			    scm_is_eq (tag, scm_out_of_range_key))
				highlights = rest;
			else
				highlights = SCM_EOL;

			scm_puts ("Backtrace:\n", port);
			scm_display_backtrace_with_highlights (captured_stack, port,
			      SCM_BOOL_F, SCM_BOOL_F, highlights);
			scm_newline (port);
		}
		scm_display_error (captured_stack, port, subr, message, parts, rest);
	}
	else
	{
		scm_puts ("ERROR: thow args are unexpectedly short!\n", port);
	}
	scm_puts("ABORT: ", port);
	scm_puts(restr, port);
	free(restr);

	return SCM_BOOL_F;
}

/* ============================================================== */

/**
 * Evaluate the expression
 */
std::string SchemeEval::eval(const std::string &expr)
{
	input_line += expr;

	caught_error = false;
	pending_input = false;
#if 0
	SCM rc = scm_internal_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this);
#endif
	captured_stack = SCM_BOOL_F;
	SCM rc = scm_c_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this,
	            SchemeEval::preunwind_handler_wrapper, this);

	if (pending_input)
	{
		return "";
	}
	pending_input = false;
	input_line = "";

	if (caught_error)
	{
		std::string rv;
		rc = scm_get_output_string(error_string_port);
		char * str = scm_to_locale_string(rc);
		rv = str;
		free(str);
		scm_close_port(error_string_port);

		scm_truncate_file(outport, scm_from_uint16(0));

		rv += "\n";
		return rv;
	}
	else
	{
		std::string rv;
		// First, we get the contents of the output port,
		// and pass that on.
		SCM out = scm_get_output_string(outport);
		char * str = scm_to_locale_string(out);
		rv = str;
		free(str);
		scm_truncate_file(outport, scm_from_uint16(0));

		// Next, we append the "interpreter" output
		rv += prt(rc);
		rv += "\n";

		return rv;
	}
	return "#<Error: Unreachable statement reached>";
}

/* ============================================================== */

/**
 * Return true if the expression was incomplete, and more is expected
 * (for example, more closing parens are expected)
 */
bool SchemeEval::input_pending(void)
{
	return pending_input;
}

/**
 * Return true if an error occured during the evaluation of the expression
 */
bool SchemeEval::eval_error(void)
{
	return caught_error;
}

/**
 * Clear the error state, the input buffers, etc.
 */
void SchemeEval::clear_pending(void)
{
	input_line = "";
	pending_input = false;
	caught_error = false;
}

#endif
/* ===================== END OF FILE ============================ */
<commit_msg>initialize *all* state<commit_after>/*
 * SchemeEval.c
 *
 * Simple scheme evaluator
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include "SchemeEval.h"

#include <libguile.h>
#include <libguile/backtrace.h>
#include <libguile/debug.h>
#include <libguile/lang.h>

#include "platform.h"
#include "SchemeSmob.h"

using namespace opencog;

bool SchemeEval::is_inited = false;

SchemeEval::SchemeEval(void)
{
	if (!is_inited)
	{
		is_inited = true;
		scm_init_guile();
		// DO NOT call scm_init_debug(), this will mess up debugging!
		// scm_init_debug();
		// scm_init_backtrace();
		// scm_init_strports(); // is this really needed ?
		SchemeSmob::init();
	}

	outport = scm_open_output_string();
	scm_set_current_output_port(outport);

	pending_input = false;
	caught_error = false;
	input_line = "";
	error_string_port = SCM_EOL;
	captured_stack = SCM_EOL;
}

/* ============================================================== */

std::string SchemeEval::prt(SCM node)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, node))
	{
		return SchemeSmob::handle_to_string(node);
	}

	else if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, node))
	{
		return SchemeSmob::misc_to_string(node);
	}

	else if (scm_is_eq(node, SCM_UNSPECIFIED))
	{
		return "";
	}
#if CUSTOM_PRINTING_WHY_DO_WE_HAVE_THIS_DELETE_ME
	else if (scm_is_pair(node))
	{
		std::string str = "(";
      SCM node_list = node;
		const char * sp = "";
      do
      {
			str += sp;
			sp = " ";
         node = SCM_CAR (node_list);
         str += prt (node);
         node_list = SCM_CDR (node_list);
      }
      while (scm_is_pair(node_list));

		// Print the rest -- the CDR part
		if (!scm_is_null(node_list))
		{
			str += " . ";
			str += prt (node_list);
		}
		str += ")";
		return str;
   }
	else if (scm_is_true(scm_symbol_p(node)))
	{
		node = scm_symbol_to_string(node);
		char * str = scm_to_locale_string(node);
		// std::string rv = "'";  // print the symbol escape
		std::string rv = "";      // err .. don't print it
		rv += str;
		free(str);
		return rv;
	}
	else if (scm_is_true(scm_string_p(node)))
	{
		char * str = scm_to_locale_string(node);
		std::string rv = "\"";
		rv += str;
		rv += "\"";
		free(str);
		return rv;
	}
	else if (scm_is_number(node))
	{
		#define NUMBUFSZ 60
		char buff[NUMBUFSZ];
		if (scm_is_signed_integer(node, INT_MIN, INT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%ld", (long) scm_to_long(node));
		}
		else if (scm_is_unsigned_integer(node, 0, UINT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%lu", (unsigned long) scm_to_ulong(node));
		}
		else if (scm_is_real(node))
		{
			snprintf (buff, NUMBUFSZ, "%g", scm_to_double(node));
		}
		else if (scm_is_complex(node))
		{
			snprintf (buff, NUMBUFSZ, "%g +i %g",
				scm_c_real_part(node),
				scm_c_imag_part(node));
		}
		else if (scm_is_rational(node))
		{
			std::string rv;
			rv = prt(scm_numerator(node));
			rv += "/";
			rv += prt(scm_denominator(node));
			return rv;
		}
		return buff;
	}
	else if (scm_is_true(scm_char_p(node)))
	{
		std::string rv;
		rv = (char) scm_to_char(node);
		return rv;
	}
	else if (scm_is_true(scm_boolean_p(node)))
	{
		if (scm_to_bool(node)) return "#t";
		return "#f";
	}
	else if (SCM_NULL_OR_NIL_P(node))
	{
		// scm_is_null(x) is true when x is SCM_EOL
		// SCM_NILP(x) is true when x is SCM_ELISP_NIL
		return "()";
	}
	else if (scm_is_eq(node, SCM_UNDEFINED))
	{
		return "undefined";
	}
	else if (scm_is_eq(node, SCM_EOF_VAL))
	{
		return "eof";
	}
#endif
	else
	{
		// Let SCM display do the rest of the work.
		SCM port = scm_open_output_string();
		scm_display (node, port);
		SCM rc = scm_get_output_string(port);
		char * str = scm_to_locale_string(rc);
		std::string rv = str;
		free(str);
		scm_close_port(port);
		return rv;
	}

	return "";
}

/* ============================================================== */

SCM SchemeEval::preunwind_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->preunwind_handler(tag, throw_args);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->catch_handler(tag, throw_args);
}

SCM SchemeEval::preunwind_handler (SCM tag, SCM throw_args)
{
	// We can only record the stack before it is unwound.
	// The normal catch handler body runs only *after* the stack
	// has been unwound.
	captured_stack = scm_make_stack (SCM_BOOL_T, SCM_EOL);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler (SCM tag, SCM throw_args)
{
	// Check for read error. If a read error, then wait for user to correct it.
	SCM re = scm_symbol_to_string(tag);
	char * restr = scm_to_locale_string(re);
	pending_input = false;
	if (0 == strcmp(restr, "read-error"))
	{
		pending_input = true;
		free(restr);
		return SCM_EOL;
	}

	// If its not a read error, then its a regular error; report it.
	caught_error = true;

	/* get string port into which we write the error message and stack. */
	error_string_port = scm_open_output_string();
	SCM port = error_string_port;

	if (scm_is_true(scm_list_p(throw_args)) && (scm_ilength(throw_args) >= 1))
	{
		long nargs = scm_ilength(throw_args);
		SCM subr    = SCM_CAR (throw_args);
		SCM message = SCM_EOL;
		if (nargs >= 2)
			message = SCM_CADR (throw_args);
		SCM parts   = SCM_EOL;
		if (nargs >= 3)
			parts   = SCM_CADDR (throw_args);
		SCM rest    = SCM_EOL;
		if (nargs >= 4)
			rest    = SCM_CADDDR (throw_args);

		if (scm_is_true (captured_stack))
		{
			SCM highlights;

			if (scm_is_eq (tag, scm_arg_type_key) ||
			    scm_is_eq (tag, scm_out_of_range_key))
				highlights = rest;
			else
				highlights = SCM_EOL;

			scm_puts ("Backtrace:\n", port);
			scm_display_backtrace_with_highlights (captured_stack, port,
			      SCM_BOOL_F, SCM_BOOL_F, highlights);
			scm_newline (port);
		}
		scm_display_error (captured_stack, port, subr, message, parts, rest);
	}
	else
	{
		scm_puts ("ERROR: thow args are unexpectedly short!\n", port);
	}
	scm_puts("ABORT: ", port);
	scm_puts(restr, port);
	free(restr);

	return SCM_BOOL_F;
}

/* ============================================================== */

/**
 * Evaluate the expression
 */
std::string SchemeEval::eval(const std::string &expr)
{
	input_line += expr;

	caught_error = false;
	pending_input = false;
#if 0
	SCM rc = scm_internal_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this);
#endif
	captured_stack = SCM_BOOL_F;
	SCM rc = scm_c_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this,
	            SchemeEval::preunwind_handler_wrapper, this);

	if (pending_input)
	{
		return "";
	}
	pending_input = false;
	input_line = "";

	if (caught_error)
	{
		std::string rv;
		rc = scm_get_output_string(error_string_port);
		char * str = scm_to_locale_string(rc);
		rv = str;
		free(str);
		scm_close_port(error_string_port);

		scm_truncate_file(outport, scm_from_uint16(0));

		rv += "\n";
		return rv;
	}
	else
	{
		std::string rv;
		// First, we get the contents of the output port,
		// and pass that on.
		SCM out = scm_get_output_string(outport);
		char * str = scm_to_locale_string(out);
		rv = str;
		free(str);
		scm_truncate_file(outport, scm_from_uint16(0));

		// Next, we append the "interpreter" output
		rv += prt(rc);
		rv += "\n";

		return rv;
	}
	return "#<Error: Unreachable statement reached>";
}

/* ============================================================== */

/**
 * Return true if the expression was incomplete, and more is expected
 * (for example, more closing parens are expected)
 */
bool SchemeEval::input_pending(void)
{
	return pending_input;
}

/**
 * Return true if an error occured during the evaluation of the expression
 */
bool SchemeEval::eval_error(void)
{
	return caught_error;
}

/**
 * Clear the error state, the input buffers, etc.
 */
void SchemeEval::clear_pending(void)
{
	input_line = "";
	pending_input = false;
	caught_error = false;
}

#endif
/* ===================== END OF FILE ============================ */
<|endoftext|>


<commit_before>#include "extensions/filters/http/grpc_http1_reverse_bridge/config.h"

#include "envoy/registry/registry.h"

#include "extensions/filters/http/grpc_http1_reverse_bridge/filter.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace GrpcHttp1ReverseBridge {

Http::FilterFactoryCb Config::createFilterFactoryFromProtoTyped(
    const envoy::config::filter::http::grpc_http1_reverse_bridge::v2alpha1::FilterConfig& config,
    const std::string&, Server::Configuration::FactoryContext&) {
  return [config](Envoy::Http::FilterChainFactoryCallbacks& callbacks) -> void {
    callbacks.addStreamFilter(
        std::make_unique<Filter>(config.content_type(), config.withhold_grpc_frames()));
  };
}

/**
 * Static registration for the grpc http1 reverse bridge filter. @see RegisterFactory.
 */
REGISTER_FACTORY(Config, Server::Configuration::NamedHttpFilterConfigFactory);

} // namespace GrpcHttp1ReverseBridge
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
<commit_msg>Use shared instead of unique ptr to avoid conversion (#8687)<commit_after>#include "extensions/filters/http/grpc_http1_reverse_bridge/config.h"

#include "envoy/registry/registry.h"

#include "extensions/filters/http/grpc_http1_reverse_bridge/filter.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace GrpcHttp1ReverseBridge {

Http::FilterFactoryCb Config::createFilterFactoryFromProtoTyped(
    const envoy::config::filter::http::grpc_http1_reverse_bridge::v2alpha1::FilterConfig& config,
    const std::string&, Server::Configuration::FactoryContext&) {
  return [config](Envoy::Http::FilterChainFactoryCallbacks& callbacks) -> void {
    callbacks.addStreamFilter(
        std::make_shared<Filter>(config.content_type(), config.withhold_grpc_frames()));
  };
}

/**
 * Static registration for the grpc http1 reverse bridge filter. @see RegisterFactory.
 */
REGISTER_FACTORY(Config, Server::Configuration::NamedHttpFilterConfigFactory);

} // namespace GrpcHttp1ReverseBridge
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
<|endoftext|>


<commit_before>#pragma once

#include <cstdlib>

#include "common.hpp"

POLYBAR_NS

template <typename T>
using malloc_ptr_t = shared_ptr<T>;

namespace memory_util {
  /**
   * Create a shared pointer using malloc/free
   */
  template <typename T, size_t Size = sizeof(T), typename Deleter = decltype(std::free)>
  inline malloc_ptr_t<T> make_malloc_ptr(Deleter deleter = std::free) {
    return malloc_ptr_t<T>(static_cast<T*>(calloc(1, Size)), deleter);
  }

  /**
   * Get the number of elements in T
   */
  template <typename T>
  inline auto countof(T& p) {
    return sizeof(p) / sizeof(p[0]);
  }
}

POLYBAR_NS_END
<commit_msg>fix(build): Ignore noexcept-type for malloc_ptr_t<commit_after>#pragma once

#include <cstdlib>

#include "common.hpp"

POLYBAR_NS

template <typename T>
using malloc_ptr_t = shared_ptr<T>;

namespace memory_util {
  /**
   * Create a shared pointer using malloc/free
   *
   * Generates a noexcept-type warning because the mangled name for
   * malloc_ptr_t will change in C++17. This doesn't affect use because we have
   * no public ABI, so we ignore it here.
   * See also this SO answer: https://stackoverflow.com/a/46857525/5363071
   */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnoexcept-type"
  template <typename T, size_t Size = sizeof(T), typename Deleter = decltype(std::free)>
  inline malloc_ptr_t<T> make_malloc_ptr(Deleter deleter = std::free) {
    return malloc_ptr_t<T>(static_cast<T*>(calloc(1, Size)), deleter);
  }
#pragma GCC diagnostic pop

  /**
   * Get the number of elements in T
   */
  template <typename T>
  inline auto countof(T& p) {
    return sizeof(p) / sizeof(p[0]);
  }
}  // namespace memory_util

POLYBAR_NS_END
<|endoftext|>


<commit_before>#ifndef V_SMC_SAMPLER_HPP
#define V_SMC_SAMPLER_HPP

#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include <vSMC/particle.hpp>
#include <vSMC/history.hpp>

namespace vSMC {

template <class T>
class Sampler
{
    public :

    /// The type of particle values
    typedef T value_type;
    /// The type of partiles
    typedef Particle<T> particle_type;
    /// The type of monitors
    typedef void (*monitor_type)
        (std::size_t iter, const Particle<T> &, double *res);

    Sampler (std::size_t N,
            std::size_t (*init) (Particle<T> &),
            std::size_t (*move) (std::size_t iter, Particle<T> &),
            void (*copy) (std::size_t, std::size_t, T &),
            HistoryMode history_mode = HISTORY_RAM,
            ResampleScheme resample_scheme = RESIDUAL,
            double resample_threshold = 0.5) :
        initialized(false), init_particle(init), move_particle(move),
        scheme(resample_scheme), threshold(resample_threshold * N),
        iter_num(0), particle(N, copy),
        ess(0), resample(false), accept(0),
        mode(history_mode), history(history_mode),
        rng(gsl_rng_alloc(gsl_rng_mt19937)), integrate_tmp(N)
    {
        gsl_rng_set(rng, 100);
    }

    ~Sampler ()
    {
        gsl_rng_free(rng);
    }

    double ESS () const
    {
        return ess;
    }

    const Particle<T> &getParticle () const
    {
        return particle;
    }

    void initialize ()
    {
        while (history.size())
            history.pop_back();
        for (std::map<std::string, std::vector<double> >::iterator
                imap = monitor_record.begin();
                imap != monitor_record.end(); ++imap)
        {
            imap->second.clear();
        }

        iter_num = 0;
        accept = init_particle(particle);
        post_move();

        initialized = true;
    }

    void iterate ()
    {
        if (!initialized)
            throw std::runtime_error(
                    "ERROR: vSMC::Sampler::iterate: "
                    "Sampler has not been initialized yet");

        ++iter_num;
        accept = move_particle(iter_num, particle);
        post_move();
    }

    void iterate (std::size_t n)
    {
        for (std::size_t i = 0; i != n; ++i)
            iterate();
    }

    double integrate (void (*integral) (
                std::size_t iter, const Particle<T> &, double *res, void *),
            void *param) const
    {
        std::size_t n = particle.size();
        integral(iter_num, particle, integrate_tmp, param);

        return cblas_ddot(n, particle.getWeightPtr(), 1, integrate_tmp, 1);
    }

    void addMonitor (const std::string &name, monitor_type integral)
    {
        monitor.insert(
                typename std::map<std::string, monitor_type>::value_type(
                    name, integral));
        monitor_record.insert(
                std::map<std::string, std::vector<double> >::value_type(
                    name, std::vector<double>()));
    }

    void removeMonitor (const std::string &name)
    {
        monitor.erase(name);
        monitor_record.erase(name);
    }

    std::vector<double> getMonitor (const std::string &name)
    {
        return monitor_record[name];
    }

    private :

    bool initialized;

    std::size_t (*init_particle) (Particle<T> &);
    std::size_t (*move_particle) (std::size_t, Particle<T> &);

    ResampleScheme scheme;
    double threshold;

    std::size_t iter_num;
    Particle<T> particle;

    double ess;
    bool resample;
    std::size_t accept;

    HistoryMode mode;
    History<T> history;

    gsl_rng *rng;

    mutable vDist::internal::Buffer<double> integrate_tmp;
    std::map<std::string, monitor_type> monitor;
    std::map<std::string, std::vector<double> > monitor_record;

    void post_move ()
    {
        ess = particle.ESS();

        if (ess < threshold) {
            particle.resample(scheme, rng);
            ess = particle.ESS();
        }

        if (mode != HISTORY_NONE) {
            history.push_back(
                    HistoryElement<T>(particle, resample, ess, accept));
        }

        for (typename std::map<std::string, monitor_type>::iterator
                imap = monitor.begin(); imap != monitor.end(); ++imap)
        {
            monitor_record.find(imap->first)->second.push_back(
                    record(imap->second));
        }
    }

    double record (monitor_type integral)
    {
        std::size_t n = particle.size();
        integral(iter_num, particle, integrate_tmp);

        return cblas_ddot(n, particle.getWeightPtr(), 1, integrate_tmp, 1);
    }
};

} // namespace vSMC

#endif // V_SMC_SAMPLER_HPP
<commit_msg>start implementation of path sampling<commit_after>#ifndef V_SMC_SAMPLER_HPP
#define V_SMC_SAMPLER_HPP

#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include <vSMC/particle.hpp>
#include <vSMC/history.hpp>

namespace vSMC {

template <class T>
class Sampler
{
    public :

    /// The type of particle values
    typedef T value_type;
    /// The type of partiles
    typedef Particle<T> particle_type;
    /// The type of monitor integration
    typedef void (*monitor_type)
        (std::size_t iter, const Particle<T> &, double *);
    /// The type of path sampling integration
    typedef double (*path_type)
        (std::size_t iter, const Particle<T> &, double *);

    Sampler (std::size_t N,
            std::size_t (*init) (Particle<T> &),
            std::size_t (*move) (std::size_t iter, Particle<T> &),
            void (*copy) (std::size_t, std::size_t, T &),
            HistoryMode history_mode = HISTORY_RAM,
            ResampleScheme resample_scheme = RESIDUAL,
            double resample_threshold = 0.5) :
        initialized(false), init_particle(init), move_particle(move),
        scheme(resample_scheme), threshold(resample_threshold * N),
        iter_num(0), particle(N, copy),
        ess(0), resample(false), accept(0),
        mode(history_mode), history(history_mode),
        rng(gsl_rng_alloc(gsl_rng_mt19937)), integrate_tmp(N),
        path_integral(NULL), path_estimate(0)
    {
        gsl_rng_set(rng, 100);
    }

    ~Sampler ()
    {
        gsl_rng_free(rng);
    }

    double ESS () const
    {
        return ess;
    }

    const Particle<T> &getParticle () const
    {
        return particle;
    }

    void initialize ()
    {
        while (history.size())
            history.pop_back();

        for (std::map<std::string, std::vector<double> >::iterator
                imap = monitor_record.begin();
                imap != monitor_record.end(); ++imap)
            imap->second.clear();

        path_sample.clear();
        path_width.clear();

        iter_num = 0;
        accept = init_particle(particle);
        post_move();

        initialized = true;
    }

    void iterate ()
    {
        if (!initialized)
            throw std::runtime_error(
                    "ERROR: vSMC::Sampler::iterate: "
                    "Sampler has not been initialized yet");

        ++iter_num;
        accept = move_particle(iter_num, particle);
        post_move();
    }

    void iterate (std::size_t n)
    {
        for (std::size_t i = 0; i != n; ++i)
            iterate();
    }

    double integrate (void (*integral) (
                std::size_t iter, const Particle<T> &, double *res, void *),
            void *param) const
    {
        std::size_t n = particle.size();
        integral(iter_num, particle, integrate_tmp, param);

        return cblas_ddot(n, particle.getWeightPtr(), 1, integrate_tmp, 1);
    }

    void addMonitor (const std::string &name, monitor_type integral)
    {
        monitor.insert(
                typename std::map<std::string, monitor_type>::value_type(
                    name, integral));
        monitor_record.insert(
                std::map<std::string, std::vector<double> >::value_type(
                    name, std::vector<double>()));
    }

    void eraseMonitor (const std::string &name)
    {
        monitor.erase(name);
        monitor_record.erase(name);
    }

    void clearMonitor ()
    {
        monitor.clear();
        monitor_record.clear();
    }

    std::vector<double> getMonitor (const std::string &name)
    {
        return monitor_record[name];
    }

    void setPathIntegral (path_type integral)
    {
        path_integral = integral;
    }

    void clearPathIntegral ()
    {
        path_integral = NULL;
    }

    double getPathIntegral () const
    {
    }

    private :

    bool initialized;

    std::size_t (*init_particle) (Particle<T> &);
    std::size_t (*move_particle) (std::size_t, Particle<T> &);

    ResampleScheme scheme;
    double threshold;

    std::size_t iter_num;
    Particle<T> particle;

    double ess;
    bool resample;
    std::size_t accept;

    HistoryMode mode;
    History<T> history;

    gsl_rng *rng;

    mutable vDist::internal::Buffer<double> integrate_tmp;
    std::map<std::string, monitor_type> monitor;
    std::map<std::string, std::vector<double> > monitor_record;

    path_type path_integral;
    std::vector<double> path_sample;
    std::vector<double> path_width;
    double path_estimate;

    void post_move ()
    {
        ess = particle.ESS();

        if (ess < threshold) {
            particle.resample(scheme, rng);
            ess = particle.ESS();
        }

        if (mode != HISTORY_NONE) {
            history.push_back(
                    HistoryElement<T>(particle, resample, ess, accept));
        }

        for (typename std::map<std::string, monitor_type>::iterator
                imap = monitor.begin(); imap != monitor.end(); ++imap)
        {
            monitor_record.find(imap->first)->second.push_back(
                    eval_monitor(imap->second));
        }

        if (path_integral) {
            double sample, width;
            sample = eval_path(path_integral, width);
            path_sample.push_back(sample);
            path_width.push_back(width);
        }
    }

    double eval_monitor (monitor_type integral)
    {
        std::size_t n = particle.size();

        integral(iter_num, particle, integrate_tmp);

        return cblas_ddot(n, particle.getWeightPtr(), 1, integrate_tmp, 1);
    }

    double eval_path (path_type integral, double &width)
    {
        std::size_t n = particle.size();

        width = integral(iter_num, particle, integrate_tmp);

        return cblas_ddot(n, particle.getWeightPtr(), 1, integrate_tmp, 1);
    }
};

} // namespace vSMC

#endif // V_SMC_SAMPLER_HPP
<|endoftext|>


<commit_before>#ifndef COFFEE_MILL_EIGEN_SOLVER
#define COFFEE_MILL_EIGEN_SOLVER
#include <array>
#include <utility>
#include <cmath>
#include <iostream>

namespace mill
{
// TODO: support eigen
class JacobiEigenSolver
{
  public:
    constexpr static std::size_t max_loop = 10000;

  public:
    JacobiEigenSolver() = default;
    ~JacobiEigenSolver() = default;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    std::array<std::pair<scalarT, matrixT<scalarT, N, 1>>, N>
    solve(const matrixT<scalarT, N, N>& mat) const;

  private:

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    bool is_symmetric(const matrixT<scalarT, N, N>& mat) const;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    std::pair<std::size_t, std::size_t>
    max_element(const matrixT<scalarT, N, N>& mat) const;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    scalarT max_relative_diff(const matrixT<scalarT, N, N>& lhs,
                              const matrixT<scalarT, N, N>& rhs) const;

    template<typename scalarT>
    static scalarT relative_tolerance();
    template<typename scalarT>
    static scalarT absolute_tolerance();
};

template<>
double JacobiEigenSolver::relative_tolerance<double>(){return 1e-13;}
template<>
float  JacobiEigenSolver::relative_tolerance<float>(){return 1e-5;}

template<>
double JacobiEigenSolver::absolute_tolerance<double>(){return 1e-13;}
template<>
float  JacobiEigenSolver::absolute_tolerance<float>(){return 1e-5;}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
std::array<std::pair<scalarT, matrixT<scalarT, N, 1>>, N>
JacobiEigenSolver::solve(const matrixT<scalarT, N, N>& mat) const
{
    if(not this->is_symmetric(mat))
        throw std::invalid_argument("asymmetric matrix");

    typedef matrixT<scalarT, N, N> Matrix;
    typedef matrixT<scalarT, N, 1> Vector;
    typedef scalarT                Real;

    Matrix m = mat;
    Matrix Ps;
    for(std::size_t i=0; i<N; ++i)
        for(std::size_t j=0; j<N; ++j)
            Ps(i, j) = (i == j) ? 1. : 0.;

    std::size_t loop=0;
    for(; loop < max_loop; ++loop)
    {
        const auto index = this->max_element(m);
        if(std::abs(m(index.first, index.second)) < absolute_tolerance<Real>())
            break;

        const Real alpha = (m(index.first, index.first) -
                            m(index.second, index.second)) * 0.5;
        const Real beta  = -1. * m(index.first, index.second);
        const Real gamma = std::abs(alpha) / std::sqrt(alpha * alpha + beta * beta);
        const Real cos_t = std::sqrt(0.5 + gamma * 0.5);
        const Real sin_t = std::copysign(std::sqrt(0.5 - gamma * 0.5), alpha * beta);

        Matrix P;
        for(std::size_t i=0; i<N; ++i)
            for(std::size_t j=0; j<N; ++j)
                P(i, j) = (i == j) ? 1. : 0.;
        P(index.first,  index.first)  =  cos_t;
        P(index.first,  index.second) =  sin_t;
        P(index.second, index.first)  = -sin_t;
        P(index.second, index.second) =  cos_t;

        Matrix tmp = transpose(P) * m * P;
        if(this->max_relative_diff(m, tmp) < relative_tolerance<Real>()) break;
        tmp(index.first,  index.second) = 0.;
        tmp(index.second, index.first)  = 0.;

        m = tmp;
        tmp = Ps * P;
        Ps = tmp;
    }
    std::cerr << "loop " << loop << "times" << std::endl;
    if(loop == max_loop)
        throw std::logic_error("cannot solve with the tolerance");

    std::array<std::pair<Real, Vector>, N> retval;
    for(std::size_t i=0; i<N; ++i)
    {
        Vector eigen;
        for(std::size_t j=0; j<N; ++j)
            eigen[j] = Ps(j, i);
        retval[i] = std::make_pair(m(i, i), eigen);
    }
    return retval;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
bool JacobiEigenSolver::is_symmetric(const matrixT<scalarT, N, N>& mat) const
{
    for(std::size_t i=0; i<N-1; ++i)
    for(std::size_t j=i+1; j<N; ++j)
        if(std::abs(mat(i, j)/mat(j, i) - 1.) > relative_tolerance<scalarT>())
            return false;
    return true;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
std::pair<std::size_t, std::size_t>
JacobiEigenSolver::max_element(const matrixT<scalarT, N, N>& mat) const
{
    scalarT max_elem = std::abs(mat(0, 1));
    std::pair<std::size_t, std::size_t> retval = std::make_pair(0, 1);

    for(std::size_t i=0; i<N-1; ++i)
        for(std::size_t j=i+1; j<N; ++j)
            if(max_elem < std::abs(mat(i, j)))
            {
                max_elem = std::abs(mat(i, j));
                retval = std::make_pair(i, j);
            }
    return retval;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
scalarT JacobiEigenSolver::max_relative_diff(const matrixT<scalarT, N, N>& lhs,
        const matrixT<scalarT, N, N>& rhs) const
{
    scalarT retval = 0.0;
    for(std::size_t i=0; i<N; ++i)
    {
        const scalarT tmp = std::abs(lhs(i, i) / rhs(i, i));
        if(retval < tmp) retval = tmp;
    }
    return retval;
}

} // mill

#endif /* COFFEE_MILL_EIGEN_SOLVER */
<commit_msg>remove dumping<commit_after>#ifndef COFFEE_MILL_EIGEN_SOLVER
#define COFFEE_MILL_EIGEN_SOLVER
#include <array>
#include <utility>
#include <cmath>

namespace mill
{
// TODO: support eigen
class JacobiEigenSolver
{
  public:
    constexpr static std::size_t max_loop = 10000;

  public:
    JacobiEigenSolver() = default;
    ~JacobiEigenSolver() = default;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    std::array<std::pair<scalarT, matrixT<scalarT, N, 1>>, N>
    solve(const matrixT<scalarT, N, N>& mat) const;

  private:

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    bool is_symmetric(const matrixT<scalarT, N, N>& mat) const;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    std::pair<std::size_t, std::size_t>
    max_element(const matrixT<scalarT, N, N>& mat) const;

    template<typename scalarT, std::size_t N,
             template<typename sT, std::size_t R, std::size_t C> class matrixT>
    scalarT max_relative_diff(const matrixT<scalarT, N, N>& lhs,
                              const matrixT<scalarT, N, N>& rhs) const;

    template<typename scalarT>
    static scalarT relative_tolerance();
    template<typename scalarT>
    static scalarT absolute_tolerance();
};

template<>
double JacobiEigenSolver::relative_tolerance<double>(){return 1e-13;}
template<>
float  JacobiEigenSolver::relative_tolerance<float>(){return 1e-5;}

template<>
double JacobiEigenSolver::absolute_tolerance<double>(){return 1e-13;}
template<>
float  JacobiEigenSolver::absolute_tolerance<float>(){return 1e-5;}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
std::array<std::pair<scalarT, matrixT<scalarT, N, 1>>, N>
JacobiEigenSolver::solve(const matrixT<scalarT, N, N>& mat) const
{
    if(not this->is_symmetric(mat))
        throw std::invalid_argument("asymmetric matrix");

    typedef matrixT<scalarT, N, N> Matrix;
    typedef matrixT<scalarT, N, 1> Vector;
    typedef scalarT                Real;

    Matrix m = mat;
    Matrix Ps;
    for(std::size_t i=0; i<N; ++i)
        for(std::size_t j=0; j<N; ++j)
            Ps(i, j) = (i == j) ? 1. : 0.;

    std::size_t loop=0;
    for(; loop < max_loop; ++loop)
    {
        const auto index = this->max_element(m);
        if(std::abs(m(index.first, index.second)) < absolute_tolerance<Real>())
            break;

        const Real alpha = (m(index.first, index.first) -
                            m(index.second, index.second)) * 0.5;
        const Real beta  = -1. * m(index.first, index.second);
        const Real gamma = std::abs(alpha) / std::sqrt(alpha * alpha + beta * beta);
        const Real cos_t = std::sqrt(0.5 + gamma * 0.5);
        const Real sin_t = std::copysign(std::sqrt(0.5 - gamma * 0.5), alpha * beta);

        Matrix P;
        for(std::size_t i=0; i<N; ++i)
            for(std::size_t j=0; j<N; ++j)
                P(i, j) = (i == j) ? 1. : 0.;
        P(index.first,  index.first)  =  cos_t;
        P(index.first,  index.second) =  sin_t;
        P(index.second, index.first)  = -sin_t;
        P(index.second, index.second) =  cos_t;

        Matrix tmp = transpose(P) * m * P;
        if(this->max_relative_diff(m, tmp) < relative_tolerance<Real>()) break;
        tmp(index.first,  index.second) = 0.;
        tmp(index.second, index.first)  = 0.;

        m = tmp;
        tmp = Ps * P;
        Ps = tmp;
    }
    if(loop == max_loop)
        throw std::logic_error("cannot solve with the tolerance");

    std::array<std::pair<Real, Vector>, N> retval;
    for(std::size_t i=0; i<N; ++i)
    {
        Vector eigen;
        for(std::size_t j=0; j<N; ++j)
            eigen[j] = Ps(j, i);
        retval[i] = std::make_pair(m(i, i), eigen);
    }
    return retval;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
bool JacobiEigenSolver::is_symmetric(const matrixT<scalarT, N, N>& mat) const
{
    for(std::size_t i=0; i<N-1; ++i)
    for(std::size_t j=i+1; j<N; ++j)
        if(std::abs(mat(i, j)/mat(j, i) - 1.) > relative_tolerance<scalarT>())
            return false;
    return true;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
std::pair<std::size_t, std::size_t>
JacobiEigenSolver::max_element(const matrixT<scalarT, N, N>& mat) const
{
    scalarT max_elem = std::abs(mat(0, 1));
    std::pair<std::size_t, std::size_t> retval = std::make_pair(0, 1);

    for(std::size_t i=0; i<N-1; ++i)
        for(std::size_t j=i+1; j<N; ++j)
            if(max_elem < std::abs(mat(i, j)))
            {
                max_elem = std::abs(mat(i, j));
                retval = std::make_pair(i, j);
            }
    return retval;
}

template<typename scalarT, std::size_t N,
         template<typename sT, std::size_t R, std::size_t C> class matrixT>
scalarT JacobiEigenSolver::max_relative_diff(const matrixT<scalarT, N, N>& lhs,
        const matrixT<scalarT, N, N>& rhs) const
{
    scalarT retval = 0.0;
    for(std::size_t i=0; i<N; ++i)
    {
        const scalarT tmp = std::abs(lhs(i, i) / rhs(i, i));
        if(retval < tmp) retval = tmp;
    }
    return retval;
}

} // mill

#endif /* COFFEE_MILL_EIGEN_SOLVER */
<|endoftext|>


<commit_before>#ifndef K3_PROFILINGBUILTINS
#define K3_PROFILINGBUILTINS

#include <cstdint>
#include <cmath>
#include <string>
#include <fstream>
#include <chrono>
#include <atomic>
#include <random>

#ifdef K3_PCM
#include <cpucounters.h>
#endif

#ifdef K3_TCMALLOC
#include "gperftools/heap-profiler.h"
#endif

#ifdef K3_JEMALLOC
#include "jemalloc/jemalloc.h"
#endif

#include "boost/thread/mutex.hpp"
#include "boost/thread/thread.hpp"

#include "Common.hpp"

namespace K3 {

class __heap_profiler {
 public:
  __heap_profiler() { heap_profiler_done.clear(); }

 protected:
  std::shared_ptr<boost::thread> heap_profiler_thread;
  std::atomic_flag heap_profiler_done;
  int time_milli() {
    auto t = std::chrono::system_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        t.time_since_epoch());
    return elapsed.count();
  }

  template <class I, class B>
  void heap_series_start(I init, B body) {
    heap_profiler_thread = make_shared<boost::thread>([this, &init, &body]() {
      std::string name = init();
      int i = 0;
      std::cout << "Heap profiling thread starting: " << name << " ("
                << time_milli() << ")" << std::endl;
      while (!heap_profiler_done.test_and_set()) {
        heap_profiler_done.clear();
        boost::this_thread::sleep_for(boost::chrono::milliseconds(250));
        body(name, i++);
      }
      std::cout << "Heap profiling thread terminating: " << name << " ("
                << time_milli() << ")" << std::endl;
    });
  }

  void heap_series_stop() {
    heap_profiler_done.test_and_set();
    if (heap_profiler_thread) {
      heap_profiler_thread->interrupt();
    }
  }
};

class ProfilingBuiltins: public __heap_profiler {
 public:
  ProfilingBuiltins();
  // PCM
  unit_t pcmStart(unit_t);
  unit_t pcmStop(unit_t);
  // TCMalloc
  unit_t tcmallocStart(unit_t);
  unit_t tcmallocStop(unit_t);
  // JEMalloc
  unit_t jemallocStart(unit_t);
  unit_t jemallocStop(unit_t);
  unit_t jemallocDump(unit_t);

 protected:
#ifdef K3_PCM
  PCM *pcm_instance_;
  shared_ptr<SystemCounterState> pcm_initial_state_;
#endif
};

}  // namespace K3

#endif
<commit_msg>Fix time_milli to use int64_t.<commit_after>#ifndef K3_PROFILINGBUILTINS
#define K3_PROFILINGBUILTINS

#include <cstdint>
#include <cmath>
#include <string>
#include <fstream>
#include <chrono>
#include <atomic>
#include <random>

#ifdef K3_PCM
#include <cpucounters.h>
#endif

#ifdef K3_TCMALLOC
#include "gperftools/heap-profiler.h"
#endif

#ifdef K3_JEMALLOC
#include "jemalloc/jemalloc.h"
#endif

#include "boost/thread/mutex.hpp"
#include "boost/thread/thread.hpp"

#include "Common.hpp"

namespace K3 {

class __heap_profiler {
 public:
  __heap_profiler() { heap_profiler_done.clear(); }

 protected:
  std::shared_ptr<boost::thread> heap_profiler_thread;
  std::atomic_flag heap_profiler_done;
  int64_t time_milli() {
    auto t = std::chrono::system_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        t.time_since_epoch());
    return elapsed.count();
  }

  template <class I, class B>
  void heap_series_start(I init, B body) {
    heap_profiler_thread = make_shared<boost::thread>([this, &init, &body]() {
      std::string name = init();
      int i = 0;
      std::cout << "Heap profiling thread starting: " << name << " ("
                << time_milli() << ")" << std::endl;
      while (!heap_profiler_done.test_and_set()) {
        heap_profiler_done.clear();
        boost::this_thread::sleep_for(boost::chrono::milliseconds(250));
        body(name, i++);
      }
      std::cout << "Heap profiling thread terminating: " << name << " ("
                << time_milli() << ")" << std::endl;
    });
  }

  void heap_series_stop() {
    heap_profiler_done.test_and_set();
    if (heap_profiler_thread) {
      heap_profiler_thread->interrupt();
    }
  }
};

class ProfilingBuiltins: public __heap_profiler {
 public:
  ProfilingBuiltins();
  // PCM
  unit_t pcmStart(unit_t);
  unit_t pcmStop(unit_t);
  // TCMalloc
  unit_t tcmallocStart(unit_t);
  unit_t tcmallocStop(unit_t);
  // JEMalloc
  unit_t jemallocStart(unit_t);
  unit_t jemallocStop(unit_t);
  unit_t jemallocDump(unit_t);

 protected:
#ifdef K3_PCM
  PCM *pcm_instance_;
  shared_ptr<SystemCounterState> pcm_initial_state_;
#endif
};

}  // namespace K3

#endif
<|endoftext|>


<commit_before>
#include "chunk_headers.hpp"
#include "magic_number.hpp"
#include "msh_builder.hpp"
#include "type_pun.hpp"
#include "ucfb_reader.hpp"

#define GLM_FORCE_CXX98
#include "glm/glm.hpp"

namespace {

#pragma pack(push, 1)

struct Xframe {
   glm::mat3 matrix;

   static_assert(std::is_standard_layout_v<glm::mat3>);
   static_assert(sizeof(glm::mat3) == 36);

   glm::vec3 position;

   static_assert(std::is_standard_layout_v<glm::vec3>);
   static_assert(sizeof(glm::vec3) == 12);
};

static_assert(std::is_standard_layout_v<Xframe>);
static_assert(sizeof(Xframe) == 48);

#pragma pack(pop)

struct Str_array {
   Magic_number mn;
   std::uint32_t size;
   char strs[];
};

static_assert(std::is_standard_layout_v<Str_array>);
static_assert(sizeof(Str_array) == 8);

struct Xframe_array {
   Magic_number mn;
   std::uint32_t size;

   Xframe xframes[];
};

static_assert(std::is_standard_layout_v<Xframe_array>);
static_assert(sizeof(Xframe_array) == 8);

auto read_xframe(const Xframe& xframe) -> std::pair<glm::vec3, glm::quat>
{
   return {xframe.position, glm::quat_cast(xframe.matrix)};
}

auto read_str_array(const Str_array& names, std::size_t count)
   -> std::vector<std::string_view>
{
   std::vector<std::string_view> strings;
   strings.reserve(count);

   for (std::size_t i{0}, head{0}; i < count; ++i) {
      if (head > names.size) throw std::runtime_error{"bad string array in skeleton"};

      strings.emplace_back(&names.strs[head]);

      head += strings.back().length() + 1;
   }

   return strings;
}

auto read_xframe_array(const Xframe_array& xfrms, std::size_t count)
   -> std::vector<std::pair<glm::vec3, glm::quat>>
{
   std::vector<std::pair<glm::vec3, glm::quat>> positions;
   positions.reserve(count);

   for (std::size_t i{0}, head{0}; i < count; ++i) {
      if (head > xfrms.size) throw std::runtime_error{"bad xframe array in skeleton"};

      positions.emplace_back(read_xframe(xfrms.xframes[i]));

      head += sizeof(Xframe);
   }

   return positions;
}

void add_bones(const std::vector<std::string_view>& names,
               const std::vector<std::string_view>& parents,
               const std::vector<std::pair<glm::vec3, glm::quat>>& positions,
               msh::Builder& builder)
{
   for (std::size_t i = 0; i < names.size(); ++i) {
      msh::Bone bone;

      bone.name = names[i];
      bone.parent = parents[i];
      bone.position = positions[i].first;
      bone.rotation = positions[i].second;

      builder.add_bone(std::move(bone));
   }
}
}

void handle_skeleton(Ucfb_reader skeleton, msh::Builders_map& builders)
{
   const auto& skel = skeleton.view_as_chunk<chunks::Skeleton>();

   const std::string name{reinterpret_cast<const char*>(&skel.bytes[0]),
                          skel.info_size - 5};

   std::uint32_t head = skel.info_size;
   const std::uint32_t end = skel.size - 8;

   const auto align_head = [&head] {
      if (head % 4 != 0) head += (4 - (head % 4));
   };
   align_head();

   const std::uint16_t bone_count =
      view_type_as<std::uint16_t>(skel.bytes[name.length() + 1]);

   std::vector<std::string_view> names;
   std::vector<std::string_view> parents;
   std::vector<std::pair<glm::vec3, glm::quat>> positions;

   while (head < end) {
      const auto& chunk = view_type_as<chunks::Unknown>(skel.bytes[head]);

      if (chunk.mn == "NAME"_mn) {
         names = read_str_array(view_type_as<Str_array>(skel.bytes[head]), bone_count);
      }
      else if (chunk.mn == "PRNT"_mn) {
         parents = read_str_array(view_type_as<Str_array>(skel.bytes[head]), bone_count);
      }
      else if (chunk.mn == "XFRM"_mn) {
         positions =
            read_xframe_array(view_type_as<Xframe_array>(skel.bytes[head]), bone_count);
      }

      head += chunk.size + 8;
      align_head();
   }

   add_bones(names, parents, positions, builders[name]);
}<commit_msg>Shifted handle_skeleton over to Ucfb_readers<commit_after>
#define GLM_FORCE_CXX98

#include "glm_pod_wrappers.hpp"
#include "magic_number.hpp"
#include "msh_builder.hpp"
#include "ucfb_reader.hpp"

#include "glm/gtc/quaternion.hpp"

namespace {

struct Xframe {
   pod::Mat3 matrix;
   pod::Vec3 position;
};

static_assert(std::is_pod_v<Xframe>);
static_assert(sizeof(Xframe) == 48);

auto read_xframe(const Xframe& xframe) -> std::pair<glm::vec3, glm::quat>
{
   return {xframe.position, glm::quat_cast(glm::mat3{xframe.matrix})};
}

template<Magic_number magic_number>
auto read_bone_names(Ucfb_reader_strict<magic_number> names, std::size_t count)
   -> std::vector<std::string_view>
{
   std::vector<std::string_view> strings;
   strings.reserve(count);

   for (std::size_t i{0}; i < count; ++i) {
      strings.emplace_back(names.read_string_unaligned());
   }

   return strings;
}

auto read_bone_xframes(Ucfb_reader_strict<"XFRM"_mn> xframes, std::size_t count)
   -> std::vector<std::pair<glm::vec3, glm::quat>>
{
   std::vector<std::pair<glm::vec3, glm::quat>> positions;
   positions.reserve(count);

   const auto xframe_array = xframes.read_array<Xframe>(count);

   for (const auto& xframe : xframe_array) {
      positions.emplace_back(read_xframe(xframe));
   }

   return positions;
}

void add_bones(const std::vector<std::string_view>& names,
               const std::vector<std::string_view>& parents,
               const std::vector<std::pair<glm::vec3, glm::quat>>& positions,
               msh::Builder& builder)
{
   for (std::size_t i = 0; i < names.size(); ++i) {
      msh::Bone bone;

      bone.name = names[i];
      bone.parent = parents[i];
      bone.position = positions[i].first;
      bone.rotation = positions[i].second;

      builder.add_bone(std::move(bone));
   }
}
}

void handle_skeleton(Ucfb_reader skeleton, msh::Builders_map& builders)
{
   auto info = skeleton.read_child_strict<"INFO"_mn>();

   const std::string name{info.read_string_unaligned()};
   const auto bone_count = info.read_trivial_unaligned<std::uint16_t>();

   std::vector<std::string_view> names =
      read_bone_names(skeleton.read_child_strict<"NAME"_mn>(), bone_count);

   std::vector<std::string_view> parents =
      read_bone_names(skeleton.read_child_strict<"PRNT"_mn>(), bone_count);

   std::vector<std::pair<glm::vec3, glm::quat>> positions =
      read_bone_xframes(skeleton.read_child_strict<"XFRM"_mn>(), bone_count);

   add_bones(names, parents, positions, builders[name]);
}<|endoftext|>