<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Copyright (C) 2012 Sergey Lisitsyn
 */

#include <shogun/lib/IndexBlockTree.h>
#include <vector>

using namespace std;
using namespace shogun;

struct tree_node_t
{
	tree_node_t** desc;
	int32_t n_desc;
	int32_t sub_nodes_count;
	int32_t idx;
};

struct block_tree_node_t
{
	block_tree_node_t(int32_t min, int32_t max, float64_t w)
	{
		t_min_index = min;
		t_max_index = max;
		weight = w;
	}
	int32_t t_min_index, t_max_index;
	float64_t weight;
};

int count_sub_nodes_recursive(tree_node_t* node, int32_t self)
{
	if (node->n_desc==0)
	{
		return 1;
	}
	else
	{
		int c = 0;
		for (int32_t i=0; i<node->n_desc; i++)
		{
			c += count_sub_nodes_recursive(node->desc[i], self);
		}
		if (self)
			node->sub_nodes_count = c;
		return c + self;
	}
}

void print_tree(tree_node_t* node, int tabs)
{
	for (int32_t t=0; t<tabs; t++)
		SG_SPRINT("  ");
	SG_SPRINT("%d %d\n",node->idx, node->sub_nodes_count);
	for (int32_t i=0; i<node->n_desc; i++)
		print_tree(node->desc[i],tabs+1);
}

int32_t fill_G_recursive(tree_node_t* node, vector<int32_t>* G)
{
	int32_t c=1;
	G->push_back(node->idx);
	for (int32_t i=0; i<node->n_desc; i++)
		c+= fill_G_recursive(node->desc[i], G);
	return c;
}

void fill_ind_recursive(tree_node_t* node, vector<block_tree_node_t>* tree_nodes, int32_t lower)
{
	int32_t l = lower;
	for (int32_t i=0; i<node->n_desc; i++)
	{
		int32_t c = node->desc[i]->sub_nodes_count;
		if (c>0)
		{
			tree_nodes->push_back(block_tree_node_t(l,l+c-1,1.0));
			fill_ind_recursive(node->desc[i], tree_nodes, l);
			l+=c;
		}
		else
			l++;
	}
}

void collect_tree_nodes_recursive(CIndexBlock* subtree_root_block, vector<block_tree_node_t>* tree_nodes)
{
	CList* sub_blocks = subtree_root_block->get_sub_blocks();
	if (sub_blocks->get_num_elements()>0)
	{
		CIndexBlock* iterator = (CIndexBlock*)sub_blocks->get_first_element();
		do
		{
			SG_SDEBUG("Block [%d %d] \n",iterator->get_min_index(), iterator->get_max_index());
			tree_nodes->push_back(block_tree_node_t(iterator->get_min_index(),iterator->get_max_index(),iterator->get_weight()));
			if (iterator->get_num_sub_blocks()>0)
				collect_tree_nodes_recursive(iterator, tree_nodes);
			SG_UNREF(iterator);
		}
		while ((iterator = (CIndexBlock*)sub_blocks->get_next_element()) != NULL);
	}
	SG_UNREF(sub_blocks);
}

CIndexBlockTree::CIndexBlockTree() :
	CIndexBlockRelation(), m_root_block(NULL),
	m_general(false)
{

}

CIndexBlockTree::CIndexBlockTree(CIndexBlock* root_block) : CIndexBlockRelation(),
	m_root_block(NULL), m_general(false)
{
	set_root_block(root_block);
}

CIndexBlockTree::CIndexBlockTree(SGMatrix<float64_t> adjacency_matrix) :
	CIndexBlockRelation(),
	m_root_block(NULL), m_general(true)
{
	ASSERT(adjacency_matrix.num_rows == adjacency_matrix.num_cols);
	int32_t n_features = adjacency_matrix.num_rows;

	// well ordering is assumed

	tree_node_t* nodes = SG_CALLOC(tree_node_t, n_features);

	int32_t* nz_row = SG_CALLOC(int32_t, n_features);
	for (int32_t i=0; i<n_features; i++)
	{
		nodes[i].idx = i;
		nodes[i].sub_nodes_count = 0;
		int32_t c = 0;
		for (int32_t j=i; j<n_features; j++)
		{
			if (adjacency_matrix(j,i)!=0.0)
				nz_row[c++] = j;
		}
		nodes[i].n_desc = c;
		nodes[i].desc = SG_MALLOC(tree_node_t*, c);
		for (int32_t j=0; j<c; j++)
		{
			nodes[i].desc[j] = &nodes[nz_row[j]];
		}
		if (nz_row[c] == n_features)
			break;
	}
	SG_FREE(nz_row);

	vector<int32_t> G;
	vector<int32_t> ind_t;
	int current_l_idx = 1;
	for (int32_t i=0; i<n_features; i++)
	{
		if (nodes[i].n_desc > 0)
		{
			int sub_count = fill_G_recursive(&nodes[i],&G);
			ind_t.push_back(current_l_idx);
			ind_t.push_back(current_l_idx+sub_count-1);
			ind_t.push_back(1.0);
			current_l_idx += sub_count;
		}
	}
	/*
	SG_SPRINT("[");
	for (int32_t i=0; i<G.size(); i++)
		SG_SPRINT(" %d ",G[i]);
	SG_SPRINT("]\n");
	SG_SPRINT("[");
	for (int32_t i=0; i<ind_t.size(); i++)
		SG_SPRINT(" %d ",ind_t[i]);
	SG_SPRINT("]\n");
	*/

	m_precomputed_ind_t = SGVector<float64_t>((int32_t)ind_t.size()+3);
	m_precomputed_ind_t[0] = -1;
	m_precomputed_ind_t[1] = -1;
	m_precomputed_ind_t[2] = 1.0;
	for (int32_t i=0; i<(int32_t)ind_t.size(); i++)
		m_precomputed_ind_t[i+3] = ind_t[i];
	m_precomputed_G = SGVector<float64_t>((int32_t)G.size());
	for (int32_t i=0; i<(int32_t)G.size(); i++)
		m_precomputed_G[i] = G[i] + 1;
	m_general = true;
	/*
	count_sub_nodes_recursive(nodes,1);
	print_tree(nodes,0);
	int32_t n_leaves = count_sub_nodes_recursive(nodes,0);
	m_precomputed_ind_t = SGVector<float64_t>((n_features-n_leaves)*3);
	SG_PRINT("n_leaves = %d\n",n_leaves);
	vector<block_tree_node_t> blocks;
	fill_ind_recursive(nodes, &blocks, 1);
	m_precomputed_ind_t[0] = -1;
	m_precomputed_ind_t[1] = -1;
	m_precomputed_ind_t[2] = 1.0;

	for (int32_t i=0; i<(int)blocks.size(); i++)
	{
		m_precomputed_ind_t[3+3*i+0] = blocks[i].t_min_index;
		m_precomputed_ind_t[3+3*i+1] = blocks[i].t_max_index;
		m_precomputed_ind_t[3+3*i+2] = blocks[i].weight;
	}
	*/
	for (int32_t i=0; i<n_features; i++)
		SG_FREE(nodes[i].desc);
	SG_FREE(nodes);
}

CIndexBlockTree::CIndexBlockTree(SGVector<float64_t> G, SGVector<float64_t> ind_t) :
	CIndexBlockRelation(),
	m_root_block(NULL), m_general(true)
{
	m_precomputed_G = G;
	m_precomputed_ind_t = ind_t;
}

CIndexBlockTree::~CIndexBlockTree()
{
	SG_UNREF(m_root_block);
}

CIndexBlock* CIndexBlockTree::get_root_block() const
{
	SG_REF(m_root_block);
	return m_root_block;
}

void CIndexBlockTree::set_root_block(CIndexBlock* root_block)
{
	SG_REF(root_block);
	SG_UNREF(m_root_block);
	m_root_block = root_block;
}

SGVector<index_t> CIndexBlockTree::get_SLEP_ind() const
{
	SG_SNOTIMPLEMENTED;
	return SGVector<index_t>();
}

SGVector<float64_t> CIndexBlockTree::get_SLEP_G() const
{
	return m_precomputed_G;
}

bool CIndexBlockTree::is_general() const
{
	return m_general;
}

SGVector<float64_t> CIndexBlockTree::get_SLEP_ind_t() const
{
	if (m_precomputed_ind_t.vlen)
		return m_precomputed_ind_t;

	else
	{
		ASSERT(m_root_block);
		CList* blocks = new CList(true);

		vector<block_tree_node_t> tree_nodes = vector<block_tree_node_t>();

		collect_tree_nodes_recursive(m_root_block, &tree_nodes);

		SGVector<float64_t> ind_t(3+3*tree_nodes.size());
		// supernode
		ind_t[0] = -1;
		ind_t[1] = -1;
		ind_t[2] = 1.0;

		for (int32_t i=0; i<(int32_t)tree_nodes.size(); i++)
		{
			ind_t[3+i*3] = tree_nodes[i].t_min_index + 1;
			ind_t[3+i*3+1] = tree_nodes[i].t_max_index;
			ind_t[3+i*3+2] = tree_nodes[i].weight;
		}

		SG_UNREF(blocks);

		return ind_t;
	}
}
<commit_msg>Removed root feature from G/ind<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Copyright (C) 2012 Sergey Lisitsyn
 */

#include <shogun/lib/IndexBlockTree.h>
#include <vector>

using namespace std;
using namespace shogun;

struct tree_node_t
{
	tree_node_t** desc;
	int32_t n_desc;
	int32_t sub_nodes_count;
	int32_t idx;
};

struct block_tree_node_t
{
	block_tree_node_t(int32_t min, int32_t max, float64_t w)
	{
		t_min_index = min;
		t_max_index = max;
		weight = w;
	}
	int32_t t_min_index, t_max_index;
	float64_t weight;
};

int count_sub_nodes_recursive(tree_node_t* node, int32_t self)
{
	if (node->n_desc==0)
	{
		return 1;
	}
	else
	{
		int c = 0;
		for (int32_t i=0; i<node->n_desc; i++)
		{
			c += count_sub_nodes_recursive(node->desc[i], self);
		}
		if (self)
			node->sub_nodes_count = c;
		return c + self;
	}
}

void print_tree(tree_node_t* node, int tabs)
{
	for (int32_t t=0; t<tabs; t++)
		SG_SPRINT("  ");
	SG_SPRINT("%d %d\n",node->idx, node->sub_nodes_count);
	for (int32_t i=0; i<node->n_desc; i++)
		print_tree(node->desc[i],tabs+1);
}

int32_t fill_G_recursive(tree_node_t* node, vector<int32_t>* G)
{
	int32_t c=1;
	G->push_back(node->idx);
	for (int32_t i=0; i<node->n_desc; i++)
		c+= fill_G_recursive(node->desc[i], G);
	return c;
}

void fill_ind_recursive(tree_node_t* node, vector<block_tree_node_t>* tree_nodes, int32_t lower)
{
	int32_t l = lower;
	for (int32_t i=0; i<node->n_desc; i++)
	{
		int32_t c = node->desc[i]->sub_nodes_count;
		if (c>0)
		{
			tree_nodes->push_back(block_tree_node_t(l,l+c-1,1.0));
			fill_ind_recursive(node->desc[i], tree_nodes, l);
			l+=c;
		}
		else
			l++;
	}
}

void collect_tree_nodes_recursive(CIndexBlock* subtree_root_block, vector<block_tree_node_t>* tree_nodes)
{
	CList* sub_blocks = subtree_root_block->get_sub_blocks();
	if (sub_blocks->get_num_elements()>0)
	{
		CIndexBlock* iterator = (CIndexBlock*)sub_blocks->get_first_element();
		do
		{
			SG_SDEBUG("Block [%d %d] \n",iterator->get_min_index(), iterator->get_max_index());
			tree_nodes->push_back(block_tree_node_t(iterator->get_min_index(),iterator->get_max_index(),iterator->get_weight()));
			if (iterator->get_num_sub_blocks()>0)
				collect_tree_nodes_recursive(iterator, tree_nodes);
			SG_UNREF(iterator);
		}
		while ((iterator = (CIndexBlock*)sub_blocks->get_next_element()) != NULL);
	}
	SG_UNREF(sub_blocks);
}

CIndexBlockTree::CIndexBlockTree() :
	CIndexBlockRelation(), m_root_block(NULL),
	m_general(false)
{

}

CIndexBlockTree::CIndexBlockTree(CIndexBlock* root_block) : CIndexBlockRelation(),
	m_root_block(NULL), m_general(false)
{
	set_root_block(root_block);
}

CIndexBlockTree::CIndexBlockTree(SGMatrix<float64_t> adjacency_matrix) :
	CIndexBlockRelation(),
	m_root_block(NULL), m_general(true)
{
	ASSERT(adjacency_matrix.num_rows == adjacency_matrix.num_cols);
	int32_t n_features = adjacency_matrix.num_rows;

	// well ordering is assumed

	tree_node_t* nodes = SG_CALLOC(tree_node_t, n_features);

	int32_t* nz_row = SG_CALLOC(int32_t, n_features);
	for (int32_t i=0; i<n_features; i++)
	{
		nodes[i].idx = i;
		nodes[i].sub_nodes_count = 0;
		int32_t c = 0;
		for (int32_t j=i; j<n_features; j++)
		{
			if (adjacency_matrix(j,i)!=0.0)
				nz_row[c++] = j;
		}
		nodes[i].n_desc = c;
		nodes[i].desc = SG_MALLOC(tree_node_t*, c);
		for (int32_t j=0; j<c; j++)
		{
			nodes[i].desc[j] = &nodes[nz_row[j]];
		}
		if (nz_row[c] == n_features)
			break;
	}
	SG_FREE(nz_row);

	vector<int32_t> G;
	vector<int32_t> ind_t;
	int current_l_idx = 1;
	for (int32_t i=1; i<n_features; i++)
	{
		if (nodes[i].n_desc > 0)
		{
			int sub_count = fill_G_recursive(&nodes[i],&G);
			ind_t.push_back(current_l_idx);
			ind_t.push_back(current_l_idx+sub_count-1);
			ind_t.push_back(1.0);
			current_l_idx += sub_count;
		}
	}
	/*
	SG_SPRINT("[");
	for (int32_t i=0; i<G.size(); i++)
		SG_SPRINT(" %d ",G[i]);
	SG_SPRINT("]\n");
	SG_SPRINT("[");
	for (int32_t i=0; i<ind_t.size(); i++)
		SG_SPRINT(" %d ",ind_t[i]);
	SG_SPRINT("]\n");
	*/

	m_precomputed_ind_t = SGVector<float64_t>((int32_t)ind_t.size()+3);
	m_precomputed_ind_t[0] = -1;
	m_precomputed_ind_t[1] = -1;
	m_precomputed_ind_t[2] = 1.0;
	for (int32_t i=0; i<(int32_t)ind_t.size(); i++)
		m_precomputed_ind_t[i+3] = ind_t[i];
	m_precomputed_G = SGVector<float64_t>((int32_t)G.size());
	for (int32_t i=0; i<(int32_t)G.size(); i++)
		m_precomputed_G[i] = G[i] + 1;
	m_general = true;
	/*
	count_sub_nodes_recursive(nodes,1);
	print_tree(nodes,0);
	int32_t n_leaves = count_sub_nodes_recursive(nodes,0);
	m_precomputed_ind_t = SGVector<float64_t>((n_features-n_leaves)*3);
	SG_PRINT("n_leaves = %d\n",n_leaves);
	vector<block_tree_node_t> blocks;
	fill_ind_recursive(nodes, &blocks, 1);
	m_precomputed_ind_t[0] = -1;
	m_precomputed_ind_t[1] = -1;
	m_precomputed_ind_t[2] = 1.0;

	for (int32_t i=0; i<(int)blocks.size(); i++)
	{
		m_precomputed_ind_t[3+3*i+0] = blocks[i].t_min_index;
		m_precomputed_ind_t[3+3*i+1] = blocks[i].t_max_index;
		m_precomputed_ind_t[3+3*i+2] = blocks[i].weight;
	}
	*/
	for (int32_t i=0; i<n_features; i++)
		SG_FREE(nodes[i].desc);
	SG_FREE(nodes);
}

CIndexBlockTree::CIndexBlockTree(SGVector<float64_t> G, SGVector<float64_t> ind_t) :
	CIndexBlockRelation(),
	m_root_block(NULL), m_general(true)
{
	m_precomputed_G = G;
	m_precomputed_ind_t = ind_t;
}

CIndexBlockTree::~CIndexBlockTree()
{
	SG_UNREF(m_root_block);
}

CIndexBlock* CIndexBlockTree::get_root_block() const
{
	SG_REF(m_root_block);
	return m_root_block;
}

void CIndexBlockTree::set_root_block(CIndexBlock* root_block)
{
	SG_REF(root_block);
	SG_UNREF(m_root_block);
	m_root_block = root_block;
}

SGVector<index_t> CIndexBlockTree::get_SLEP_ind() const
{
	SG_SNOTIMPLEMENTED;
	return SGVector<index_t>();
}

SGVector<float64_t> CIndexBlockTree::get_SLEP_G() const
{
	return m_precomputed_G;
}

bool CIndexBlockTree::is_general() const
{
	return m_general;
}

SGVector<float64_t> CIndexBlockTree::get_SLEP_ind_t() const
{
	if (m_precomputed_ind_t.vlen)
		return m_precomputed_ind_t;

	else
	{
		ASSERT(m_root_block);
		CList* blocks = new CList(true);

		vector<block_tree_node_t> tree_nodes = vector<block_tree_node_t>();

		collect_tree_nodes_recursive(m_root_block, &tree_nodes);

		SGVector<float64_t> ind_t(3+3*tree_nodes.size());
		// supernode
		ind_t[0] = -1;
		ind_t[1] = -1;
		ind_t[2] = 1.0;

		for (int32_t i=0; i<(int32_t)tree_nodes.size(); i++)
		{
			ind_t[3+i*3] = tree_nodes[i].t_min_index + 1;
			ind_t[3+i*3+1] = tree_nodes[i].t_max_index;
			ind_t[3+i*3+2] = tree_nodes[i].weight;
		}

		SG_UNREF(blocks);

		return ind_t;
	}
}
<|endoftext|>


<commit_before>#ifndef FILTER_FALSE__HPP__
#define FILTER_FALSE__HPP__

#include "filter.hpp"

namespace iter {

    namespace detail {

        // Callable object that reverses the boolean result of another
        // callable, taking the object in a Container's iterator
        template <typename FilterFunc, typename Container>
        class PredicateFlipper {
            private:
                FilterFunc filter_func;

                using contained_iter_ret =
                    decltype(std::declval<Container>().begin().operator*());

            public:
                PredicateFlipper(FilterFunc filter_func) :
                    filter_func(filter_func)
                { }

                PredicateFlipper() = delete;
                PredicateFlipper(const PredicateFlipper &) = default;

                // Calls the filter_func
                bool operator() (const contained_iter_ret item) const {
                    return !bool(filter_func(item));
                }
        };

        // Reverses the bool() conversion result of anything that supports a
        // bool conversion
        template <typename Container>
        class BoolFlipper : public BoolTester<Container> {
            private:
                using contained_iter_ret =
                    typename BoolTester<Container>::contained_iter_ret;

            public:
                bool operator() (const contained_iter_ret item) const {
                    return !bool(item);
                }
        };

    }

    // Creates a PredicateFlipper for the predicate function, which reverses
    // the bool result of the function.  The PredicateFlipper is then passed
    // to the normal filter() function
    template <typename FilterFunc, typename Container>
    auto filterfalse(FilterFunc filter_func, Container & container) ->
            decltype(filter(detail::PredicateFlipper<FilterFunc, Container>(
                            filter_func), container)) {
        return filter(
                detail::PredicateFlipper<FilterFunc, Container>(filter_func),
                container);
    }

    // Single argument version, uses a BoolFlipper to reverse the truthiness
    // of an object
    template <typename Container>
    auto filterfalse(Container & container) ->
            decltype(filter(detail::BoolFlipper<Container>(), container)) {
        return filter(detail::BoolFlipper<Container>(), container);
    }

}

#endif //#ifndef FILTER_FALSE__HPP__
<commit_msg>Use iterbase type aliases<commit_after>#ifndef FILTER_FALSE__HPP__
#define FILTER_FALSE__HPP__

#include <iterbase.hpp>
#include <filter.hpp>

namespace iter {

    namespace detail {

        // Callable object that reverses the boolean result of another
        // callable, taking the object in a Container's iterator
        template <typename FilterFunc, typename Container>
        class PredicateFlipper {
            private:
                FilterFunc filter_func;

                using contained_iter_ret =
                    typename IterBase<Container>::contained_iter_ret;

            public:
                PredicateFlipper(FilterFunc filter_func) :
                    filter_func(filter_func)
                { }

                PredicateFlipper() = delete;
                PredicateFlipper(const PredicateFlipper &) = default;

                // Calls the filter_func
                bool operator() (const contained_iter_ret item) const {
                    return !bool(filter_func(item));
                }
        };

        // Reverses the bool() conversion result of anything that supports a
        // bool conversion
        template <typename Container>
        class BoolFlipper : public BoolTester<Container> {
            private:
                using contained_iter_ret =
                    typename BoolTester<Container>::contained_iter_ret;

            public:
                bool operator() (const contained_iter_ret item) const {
                    return !bool(item);
                }
        };

    }

    // Creates a PredicateFlipper for the predicate function, which reverses
    // the bool result of the function.  The PredicateFlipper is then passed
    // to the normal filter() function
    template <typename FilterFunc, typename Container>
    auto filterfalse(FilterFunc filter_func, Container & container) ->
            decltype(filter(detail::PredicateFlipper<FilterFunc, Container>(
                            filter_func), container)) {
        return filter(
                detail::PredicateFlipper<FilterFunc, Container>(filter_func),
                container);
    }

    // Single argument version, uses a BoolFlipper to reverse the truthiness
    // of an object
    template <typename Container>
    auto filterfalse(Container & container) ->
            decltype(filter(detail::BoolFlipper<Container>(), container)) {
        return filter(detail::BoolFlipper<Container>(), container);
    }

}

#endif //#ifndef FILTER_FALSE__HPP__
<|endoftext|>


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

#include "CompressorRGBE.h"
#include "CompressionOptions.h"
#include "OutputOptions.h"

#include <nvimage/Image.h>
#include <nvimage/FloatImage.h>

#include <nvmath/Color.h>

#include <nvcore/Debug.h>

using namespace nv;
using namespace nvtt;

static Color32 toRgbe8(float r, float g, float b)
{
    Color32 c;
    float v = max(max(r, g), b);
    if (v < 1e-32) {
        c.r = c.g = c.b = c.a = 0;
    }
    else {
        int e;
        v = frexp(v, &e) * 256.0f / v;
        c.r = uint8(clamp(r * v, 0.0f, 255.0f));
        c.g = uint8(clamp(g * v, 0.0f, 255.0f));
        c.b = uint8(clamp(b * v, 0.0f, 255.0f));
        c.a = e + 128;
    }

    return c;
}

void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
    nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);

    uint srcPitch = w;
    uint srcPlane = w * h;

    // Allocate output scanline.
	Color32 * dst = (Color32 *)mem::malloc(w);

	for (uint y = 0; y < h; y++)
	{
        const uint * src = (const uint *)data + y * srcPitch;
        const float * fsrc = (const float *)data + y * srcPitch;

		for (uint x = 0; x < w; x++)
		{
            float r, g, b;

            if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
                Color32 c = Color32(src[x]);
                r = float(c.r) / 255.0f;
                g = float(c.g) / 255.0f;
                b = float(c.b) / 255.0f;
            }
            else {
                nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);

#pragma message("Interleave color components")

			    // Color components not interleaved.
			    r = fsrc[x + 0 * srcPlane];
			    g = fsrc[x + 1 * srcPlane];
			    b = fsrc[x + 2 * srcPlane];
            }

            dst[x] = toRgbe8(r, g, b);
        }

		if (outputOptions.outputHandler != NULL)
		{
			outputOptions.outputHandler->writeData(dst, w * 4);
		}
    }

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

#include "CompressorRGBE.h"
#include "CompressionOptions.h"
#include "OutputOptions.h"

#include <nvimage/Image.h>
#include <nvimage/FloatImage.h>

#include <nvmath/Color.h>

#include <nvcore/Debug.h>

using namespace nv;
using namespace nvtt;

static Color32 toRgbe8(float r, float g, float b)
{
    Color32 c;
    float v = max(max(r, g), b);
    if (v < 1e-32) {
        c.r = c.g = c.b = c.a = 0;
    }
    else {
        int e;
        v = frexp(v, &e) * 256.0f / v;
        c.r = uint8(clamp(r * v, 0.0f, 255.0f));
        c.g = uint8(clamp(g * v, 0.0f, 255.0f));
        c.b = uint8(clamp(b * v, 0.0f, 255.0f));
        c.a = e + 128;
    }

    return c;
}

void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
    nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);

    uint srcPitch = w;
    uint srcPlane = w * h;

    // Allocate output scanline.
	Color32 * dst = (Color32 *)mem::malloc(w);

	for (uint y = 0; y < h; y++)
	{
        const uint * src = (const uint *)data + y * srcPitch;
        const float * fsrc = (const float *)data + y * srcPitch;

		for (uint x = 0; x < w; x++)
		{
            float r, g, b;

            if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
                Color32 c = Color32(src[x]);
                r = float(c.r) / 255.0f;
                g = float(c.g) / 255.0f;
                b = float(c.b) / 255.0f;
            }
            else {
                nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);

#pragma message(NV_FILE_LINE "TODO: Interleave color components")

			    // Color components not interleaved.
			    r = fsrc[x + 0 * srcPlane];
			    g = fsrc[x + 1 * srcPlane];
			    b = fsrc[x + 2 * srcPlane];
            }

            dst[x] = toRgbe8(r, g, b);
        }

		if (outputOptions.outputHandler != NULL)
		{
			outputOptions.outputHandler->writeData(dst, w * 4);
		}
    }

	mem::free(dst);
}
<|endoftext|>


<commit_before><commit_msg>`ObjectStruct`: removed `ontology::Symbiosis* symbiosis_parent`.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <iostream>

#include    "Stroika/Foundation/Characters/String2Float.h"
#include    "Stroika/Foundation/DataExchange/JSON/Writer.h"
#include    "Stroika/Foundation/Execution/CommandLine.h"
#include    "Stroika/Foundation/Execution/Sleep.h"
#if     qPlatform_POSIX
#include    "Stroika/Foundation/Execution/SignalHandlers.h"
#endif
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/Streams/BasicBinaryOutputStream.h"

#include    "Stroika/Frameworks/SystemPerformance/AllInstruments.h"
#include    "Stroika/Frameworks/SystemPerformance/Capturer.h"
#include    "Stroika/Frameworks/SystemPerformance/Measurement.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Frameworks;
using   namespace Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String;
using   Containers::Sequence;
using   Memory::Optional;

namespace {
    string  Serialize_ (VariantValue v, bool oneLineMode)
    {
        Streams::BasicBinaryOutputStream    out;
        DataExchange::JSON::Writer ().Write (v, out);
        // strip CRLF - so shows up on one line
        String result = String::FromUTF8 (out.As<string> ());
        if (oneLineMode) {
            result = result.StripAll ([] (Character c)-> bool { return c == '\n' or c == '\r';});
        }
        return result.AsNarrowSDKString ();
    }
}

int main (int argc, const char* argv[])
{
#if     qPlatform_POSIX
    // Many performance instruments use pipes
    // @todo - REVIEW IF REALLY NEEDED AND WHY? SO LONG AS NO FAIL SHOULDNT BE?
    //  --LGP 2014-02-05
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    bool                        printUsage      =   false;
    bool                        printNames      =   false;
    bool                        oneLineMode     =   false;
    Time::DurationSecondsType   runFor          =   0;              // default to runfor 0, so we do each once.
    Time::DurationSecondsType   captureInterval =   1;
    Set<InstrumentNameType> run;
    Sequence<String>  args    =   Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end(); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"h")) {
            printUsage = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"l")) {
            printNames = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"o")) {
            oneLineMode = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"r")) {
            ++argi;
            if (argi != args.end ()) {
                run.Add (*argi);
            }
            else {
                cerr << "Expected arg to -r" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"t")) {
            ++argi;
            if (argi != args.end ()) {
                runFor = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -t" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"c")) {
            ++argi;
            if (argi != args.end ()) {
                captureInterval = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -c" << endl;
                return EXIT_FAILURE;
            }
        }
    }
    if (printUsage) {
        cerr << "Usage: SystemPerformanceClient [-h] [-l] [-f] [-r RUN-INSTRUMENT]*" << endl;
        cerr << "    -h prints this help" << endl;
        cerr << "    -o prints instrument results (with newlines stripped)" << endl;
        cerr << "    -l prints only the instrument names" << endl;
        cerr << "    -r runs the given instrument (it can be repeated)" << endl;
        cerr << "    -t time to run for (if zero run each matching instrument once)" << endl;
        cerr << "    -c time interval between captures" << endl;
        return EXIT_SUCCESS;
    }

    try {
        if (printNames) {
            cout << "Instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                // print measurements too?
            }
            return EXIT_SUCCESS;
        }

        bool    useCapturer =   runFor > 0;
        if (useCapturer) {
            /*
             * Demo using capturer
             */
            Capturer capturer;
            {
                CaptureSet cs;
                cs.SetRunPeriod (Duration (15));
                for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                    if (not run.empty ()) {
                        if (not run.Contains (i.fInstrumentName)) {
                            continue;
                        }
                    }
                    cs.AddInstrument (i);
                }
                capturer.AddCaptureSet (cs);
            }
            capturer.AddMeasurementsCallback ([oneLineMode] (MeasurementSet ms) {
                cout << "    Measured-At: " << ms.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                for (Measurement mi : ms.fMeasurements) {
                    cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                }
            });

            // run til timeout and then fall out...
            IgnoreExceptionsForCall (Execution::WaitableEvent (Execution::WaitableEvent::eAutoReset).Wait (runFor));
        }
        else {
            /*
             * Demo NOT using capturer
             */
            cout << "Results for each instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                if (not run.empty ()) {
                    if (not run.Contains (i.fInstrumentName)) {
                        continue;
                    }
                }
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                Execution::Sleep (captureInterval);
                MeasurementSet m = i.Capture ();
                if (m.fMeasurements.empty ()) {
                    cout << "    NO DATA";
                }
                else {
                    cout << "    Measured-At: " << m.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                    for (Measurement mi : m.fMeasurements) {
                        cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                    }
                }
            }
        }
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<commit_msg>Avoid deprecated Streams::BasicBinaryOutputStream<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <iostream>

#include    "Stroika/Foundation/Characters/String2Float.h"
#include    "Stroika/Foundation/DataExchange/JSON/Writer.h"
#include    "Stroika/Foundation/Execution/CommandLine.h"
#include    "Stroika/Foundation/Execution/Sleep.h"
#if     qPlatform_POSIX
#include    "Stroika/Foundation/Execution/SignalHandlers.h"
#endif
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/Streams/MemoryStream.h"

#include    "Stroika/Frameworks/SystemPerformance/AllInstruments.h"
#include    "Stroika/Frameworks/SystemPerformance/Capturer.h"
#include    "Stroika/Frameworks/SystemPerformance/Measurement.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Frameworks;
using   namespace Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String;
using   Containers::Sequence;
using   Memory::Byte;
using   Memory::Optional;

namespace {
    string  Serialize_ (VariantValue v, bool oneLineMode)
    {
        Streams::MemoryStream<Byte>    out;
        DataExchange::JSON::Writer ().Write (v, out);
        // strip CRLF - so shows up on one line
        String result = String::FromUTF8 (out.As<string> ());
        if (oneLineMode) {
            result = result.StripAll ([] (Character c)-> bool { return c == '\n' or c == '\r';});
        }
        return result.AsNarrowSDKString ();
    }
}

int main (int argc, const char* argv[])
{
#if     qPlatform_POSIX
    // Many performance instruments use pipes
    // @todo - REVIEW IF REALLY NEEDED AND WHY? SO LONG AS NO FAIL SHOULDNT BE?
    //  --LGP 2014-02-05
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    bool                        printUsage      =   false;
    bool                        printNames      =   false;
    bool                        oneLineMode     =   false;
    Time::DurationSecondsType   runFor          =   0;              // default to runfor 0, so we do each once.
    Time::DurationSecondsType   captureInterval =   1;
    Set<InstrumentNameType> run;
    Sequence<String>  args    =   Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end(); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"h")) {
            printUsage = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"l")) {
            printNames = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"o")) {
            oneLineMode = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"r")) {
            ++argi;
            if (argi != args.end ()) {
                run.Add (*argi);
            }
            else {
                cerr << "Expected arg to -r" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"t")) {
            ++argi;
            if (argi != args.end ()) {
                runFor = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -t" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"c")) {
            ++argi;
            if (argi != args.end ()) {
                captureInterval = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -c" << endl;
                return EXIT_FAILURE;
            }
        }
    }
    if (printUsage) {
        cerr << "Usage: SystemPerformanceClient [-h] [-l] [-f] [-r RUN-INSTRUMENT]*" << endl;
        cerr << "    -h prints this help" << endl;
        cerr << "    -o prints instrument results (with newlines stripped)" << endl;
        cerr << "    -l prints only the instrument names" << endl;
        cerr << "    -r runs the given instrument (it can be repeated)" << endl;
        cerr << "    -t time to run for (if zero run each matching instrument once)" << endl;
        cerr << "    -c time interval between captures" << endl;
        return EXIT_SUCCESS;
    }

    try {
        if (printNames) {
            cout << "Instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                // print measurements too?
            }
            return EXIT_SUCCESS;
        }

        bool    useCapturer =   runFor > 0;
        if (useCapturer) {
            /*
             * Demo using capturer
             */
            Capturer capturer;
            {
                CaptureSet cs;
                cs.SetRunPeriod (Duration (15));
                for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                    if (not run.empty ()) {
                        if (not run.Contains (i.fInstrumentName)) {
                            continue;
                        }
                    }
                    cs.AddInstrument (i);
                }
                capturer.AddCaptureSet (cs);
            }
            capturer.AddMeasurementsCallback ([oneLineMode] (MeasurementSet ms) {
                cout << "    Measured-At: " << ms.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                for (Measurement mi : ms.fMeasurements) {
                    cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                }
            });

            // run til timeout and then fall out...
            IgnoreExceptionsForCall (Execution::WaitableEvent (Execution::WaitableEvent::eAutoReset).Wait (runFor));
        }
        else {
            /*
             * Demo NOT using capturer
             */
            cout << "Results for each instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                if (not run.empty ()) {
                    if (not run.Contains (i.fInstrumentName)) {
                        continue;
                    }
                }
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                Execution::Sleep (captureInterval);
                MeasurementSet m = i.Capture ();
                if (m.fMeasurements.empty ()) {
                    cout << "    NO DATA";
                }
                else {
                    cout << "    Measured-At: " << m.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                    for (Measurement mi : m.fMeasurements) {
                        cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                    }
                }
            }
        }
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2004-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "AlignPoints.h"
#include <RDGeneral/Invariant.h>
#include <Geometry/point.h>
#include <Geometry/Transform3D.h>
#include <Numerics/Vector.h>

#define TOLERANCE 1.e-6

namespace RDNumeric {

  namespace Alignments {

    RDGeom::Point3D _weightedSumOfPoints(const RDGeom::Point3DConstPtrVect &points,
                                         const DoubleVector &weights) {
      PRECONDITION(points.size() == weights.size(), "");
      RDGeom::Point3DConstPtrVect_CI pti;
      RDGeom::Point3D tmpPt, res;
      const double *wData = weights.getData();
      unsigned int i = 0;
      for (pti = points.begin(); pti != points.end(); pti++) {
        tmpPt = (*(*pti));
        tmpPt *= wData[i];
        res += tmpPt;
        i++;
      }
      return res;
    }

    double _weightedSumOfLenSq(const RDGeom::Point3DConstPtrVect &points,
                               const DoubleVector &weights) {
      PRECONDITION(points.size() == weights.size(), "");
      double res = 0.0;
      RDGeom::Point3DConstPtrVect_CI pti;
      const double *wData = weights.getData();
      unsigned int i = 0;
      for (pti = points.begin(); pti != points.end(); pti++) {
        res += (wData[i]*((*pti)->lengthSq()));
        i++;
      }
      return res;
    }

    double _sumOfWeights(const DoubleVector &weights) {
      const double *wData = weights.getData();
      double res = 0.0;
      for (unsigned int i = 0; i < weights.size(); i++) {
        CHECK_INVARIANT(wData[i] > 0.0, "Negative weight specified for a point");
        res += wData[i];
      }
      return res;
    }

    void _computeCovarianceMat(const RDGeom::Point3DConstPtrVect &refPoints,
                               const RDGeom::Point3DConstPtrVect &probePoints,
                               const DoubleVector &weights,
                               double covMat[3][3]) {
      unsigned int i, j;
      for (i = 0; i < 3; i++) {
        for (j=0; j < 3; j++) {
          covMat[i][j] = 0.0;
        }
      }
      unsigned int npt = refPoints.size();
      CHECK_INVARIANT(npt == probePoints.size(), "Number of points mismatch");
      CHECK_INVARIANT(npt == weights.size(), "Number of points and number of weights do not match");
      const double *wData = weights.getData();

      const RDGeom::Point3D *rpt, *ppt;
      double w;
      for (i = 0; i < npt; i++) {
        rpt = refPoints[i];
        ppt = probePoints[i];
        w = wData[i];

        covMat[0][0] += w*(ppt->x)*(rpt->x);
        covMat[0][1] += w*(ppt->x)*(rpt->y);
        covMat[0][2] += w*(ppt->x)*(rpt->z);

        covMat[1][0] += w*(ppt->y)*(rpt->x);
        covMat[1][1] += w*(ppt->y)*(rpt->y);
        covMat[1][2] += w*(ppt->y)*(rpt->z);

        covMat[2][0] += w*(ppt->z)*(rpt->x);
        covMat[2][1] += w*(ppt->z)*(rpt->y);
        covMat[2][2] += w*(ppt->z)*(rpt->z);
      }
    }

    void _covertCovMatToQuad(const double covMat[3][3],
                             const RDGeom::Point3D &rptSum, const RDGeom::Point3D &pptSum,
                             double wtsSum, double quad[4][4]) {
      double PxRx, PxRy, PxRz;
      double PyRx, PyRy, PyRz;
      double PzRx, PzRy, PzRz;
      double temp;

      temp = pptSum.x/wtsSum;
      PxRx = covMat[0][0] - temp*rptSum.x;
      PxRy = covMat[0][1] - temp*rptSum.y;
      PxRz = covMat[0][2] - temp*rptSum.z;

      temp = pptSum.y/wtsSum;
      PyRx = covMat[1][0] - temp*rptSum.x;
      PyRy = covMat[1][1] - temp*rptSum.y;
      PyRz = covMat[1][2] - temp*rptSum.z;

      temp = pptSum.z/wtsSum;
      PzRx = covMat[2][0] - temp*rptSum.x;
      PzRy = covMat[2][1] - temp*rptSum.y;
      PzRz = covMat[2][2] - temp*rptSum.z;

      quad[0][0] = -2.0*(PxRx + PyRy + PzRz);
      quad[1][1] = -2.0*(PxRx - PyRy - PzRz);
      quad[2][2] = -2.0*(PyRy - PzRz - PxRx);
      quad[3][3] = -2.0*(PzRz - PxRx - PyRy);

      quad[0][1] = quad[1][0] = 2.0*(PyRz - PzRy);
      quad[0][2] = quad[2][0] = 2.0*(PzRx - PxRz);
      quad[0][3] = quad[3][0] = 2.0*(PxRy - PyRx);
      quad[1][2] = quad[2][1] = -2.0*(PxRy + PyRx);
      quad[1][3] = quad[3][1] = -2.0*(PzRx + PxRz);
      quad[2][3] = quad[3][2] = -2.0*(PyRz + PzRy);
    }

    //! Obtain the eigen vectors and eigen values
    /*!
      \param quad        4x4 matrix of interest
      \param eigenVals   storage for eigen values
      \param eigenVecs   storage for eigen vectors
      \param maxIter     max number of iterations

      <b>Reference:<\b>
      This is essentailly a copy of the jacobi routine taken from the program
      quatfit.c available from the Computational Chemistry Archives.
      http://www.ccl.net/cca/software/SOURCES/C/quaternion-mol-fit/index.shtml
      E-mail jkl@osc.edu for details.
      It was written by:

      David J. Heisterberg
      The Ohio Supercomputer Center
      1224 Kinnear Rd.
      Columbus, OH  43212-1163
      (614)292-6036
      djh@osc.edu    djh@ohstpy.bitnet    ohstpy::djh
      Copyright: Ohio Supercomputer Center, David J. Heisterberg, 1990.
      The program can be copied and distributed freely, provided that
      this copyright in not removed. You may acknowledge the use of the
      program in published material as:
      David J. Heisterberg, 1990, unpublished results.

      Also see page 463 in Numerical Recipes in C (second edition)
    */

    unsigned int jacobi (double quad[4][4], double eigenVals[4], double eigenVecs[4][4],
                unsigned int maxIter) {
      double offDiagNorm, diagNorm;
      double b, dma, q, t, c, s;
      double atemp, vtemp, dtemp;
      int i, j, k;
      unsigned int l;

      // initialize the eigen vector to Identity
      for (j = 0; j <= 3; j++) {
        for (i = 0; i <= 3; i++) eigenVecs[i][j] = 0.0;
        eigenVecs[j][j] = 1.0;
        eigenVals[j] = quad[j][j];
      }

      for (l = 0; l < maxIter; l++) {
        diagNorm = 0.0;
        offDiagNorm = 0.0;
        for (j = 0; j <= 3; j++) {
          diagNorm += fabs(eigenVals[j]);
          for (i = 0; i <= j - 1; i++) {
            offDiagNorm += fabs(quad[i][j]);
          }
        }
        if((offDiagNorm/diagNorm) <= TOLERANCE)
          goto Exit_now;
        for (j = 1; j <= 3; j++) {
          for (i = 0; i <= j - 1; i++) {
            b = quad[i][j];
            if(fabs(b) > 0.0) {
              dma = eigenVals[j] - eigenVals[i];
              if((fabs(dma) + fabs(b)) <=  fabs(dma)) {
                t = b / dma;
              }
              else {
                q = 0.5 * dma / b;
                t = 1.0/(fabs(q) + sqrt(1.0+q*q));
                if(q < 0.0) {
                  t = -t;
                }
              }
              c = 1.0/sqrt(t * t + 1.0);
              s = t * c;
              quad[i][j] = 0.0;
              for (k = 0; k <= i-1; k++) {
                atemp = c * quad[k][i] - s * quad[k][j];
                quad[k][j] = s * quad[k][i] + c * quad[k][j];
                quad[k][i] = atemp;
              }
              for (k = i+1; k <= j-1; k++) {
                atemp = c * quad[i][k] - s * quad[k][j];
                quad[k][j] = s * quad[i][k] + c * quad[k][j];
                quad[i][k] = atemp;
              }
              for (k = j+1; k <= 3; k++) {
                atemp = c * quad[i][k] - s * quad[j][k];
                quad[j][k] = s * quad[i][k] + c * quad[j][k];
                quad[i][k] = atemp;
              }
              for (k = 0; k <= 3; k++) {
                vtemp = c * eigenVecs[k][i] - s * eigenVecs[k][j];
                eigenVecs[k][j] = s * eigenVecs[k][i] + c * eigenVecs[k][j];
                eigenVecs[k][i] = vtemp;
              }
              dtemp = c*c*eigenVals[i] + s*s*eigenVals[j] - 2.0*c*s*b;
              eigenVals[j] = s*s*eigenVals[i] + c*c*eigenVals[j] +  2.0*c*s*b;
              eigenVals[i] = dtemp;
            }  /* end if */
          } /* end for i */
        } /* end for j */
      } /* end for l */

    Exit_now:

      for (j = 0; j <= 2; j++) {
        k = j;
        dtemp = eigenVals[k];
        for (i = j+1; i <= 3; i++) {
          if(eigenVals[i] < dtemp) {
            k = i;
            dtemp = eigenVals[k];
          }
        }

        if(k > j) {
          eigenVals[k] = eigenVals[j];
          eigenVals[j] = dtemp;
          for (i = 0; i <= 3; i++) {
            dtemp = eigenVecs[i][k];
            eigenVecs[i][k] = eigenVecs[i][j];
            eigenVecs[i][j] = dtemp;
          }
        }
      }
      return l+1;
    }

    void reflectCovMat(double covMat[3][3]) {
      unsigned int i, j;
      for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
          covMat[i][j] = -covMat[i][j];
        }
      }
    }

    double AlignPoints(const RDGeom::Point3DConstPtrVect &refPoints,
                       const RDGeom::Point3DConstPtrVect &probePoints,
                       RDGeom::Transform3D &trans,
                       const DoubleVector *weights, bool reflect,
                       unsigned int maxIterations) {
      unsigned int npt = refPoints.size();
      PRECONDITION(npt == probePoints.size(), "Mismatch in number of points");
      trans.setToIdentity();
      const DoubleVector *wts;
      double wtsSum;
      if (weights) {
        PRECONDITION(npt == weights->size(), "Mismatch in number of points");
        wts = weights;
        wtsSum = _sumOfWeights(*wts);
      } else {
        wts = new DoubleVector(npt, 1.0);
        wtsSum = static_cast<double>(npt);
      }

      RDGeom::Point3D rptSum = _weightedSumOfPoints(refPoints, *wts);
      RDGeom::Point3D pptSum = _weightedSumOfPoints(probePoints, *wts);

      double rptSumLenSq = _weightedSumOfLenSq(refPoints, *wts);
      double pptSumLenSq = _weightedSumOfLenSq(probePoints, *wts);

      double covMat[3][3];

      // compute the co-variance matrix
      _computeCovarianceMat(refPoints, probePoints, *wts, covMat);

      if (reflect) {
        rptSum *= -1.0;
        reflectCovMat(covMat);
      }

      // convert the covariance matrix to a 4x4 matrix that needs to be diagonalized
      double quad[4][4];
      _covertCovMatToQuad(covMat, rptSum, pptSum, wtsSum, quad);

      // get the eigenVecs and eigenVals for the matrix
      double eigenVecs[4][4], eigenVals[4];
      unsigned int numIter;
      numIter = jacobi(quad, eigenVals, eigenVecs, maxIterations);

      // get the quaternion
      double quater[4];
      quater[0] = eigenVecs[0][0];
      quater[1] = eigenVecs[1][0];
      quater[2] = eigenVecs[2][0];
      quater[3] = eigenVecs[3][0];

      trans.SetRotationFromQuaternion(quater);
      if (reflect) {
        // put the flip in the rotation matrix
        trans.Reflect();
      }
      // compute the SSR value
      double ssr = eigenVals[0] - (pptSum.lengthSq() + rptSum.lengthSq())/wtsSum
        + rptSumLenSq + pptSumLenSq;

      if ((ssr < 0.0) && (fabs(ssr) < TOLERANCE)) {
        ssr = 0.0;
      }
      if (reflect) {
        rptSum *= -1.0;
      }

      // set the translation
      trans.TransformPoint(pptSum);
      RDGeom::Point3D move = rptSum;
      move -= pptSum;
      move /= wtsSum;
      trans.SetTranslation(move);
      return ssr;
    }
  }
}

<commit_msg>fix sf.net issue 1899787: core leak in getAlignmentTransform<commit_after>// $Id$
//
//  Copyright (C) 2004-2008 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "AlignPoints.h"
#include <RDGeneral/Invariant.h>
#include <Geometry/point.h>
#include <Geometry/Transform3D.h>
#include <Numerics/Vector.h>

#define TOLERANCE 1.e-6

namespace RDNumeric {

  namespace Alignments {

    RDGeom::Point3D _weightedSumOfPoints(const RDGeom::Point3DConstPtrVect &points,
                                         const DoubleVector &weights) {
      PRECONDITION(points.size() == weights.size(), "");
      RDGeom::Point3DConstPtrVect_CI pti;
      RDGeom::Point3D tmpPt, res;
      const double *wData = weights.getData();
      unsigned int i = 0;
      for (pti = points.begin(); pti != points.end(); pti++) {
        tmpPt = (*(*pti));
        tmpPt *= wData[i];
        res += tmpPt;
        i++;
      }
      return res;
    }

    double _weightedSumOfLenSq(const RDGeom::Point3DConstPtrVect &points,
                               const DoubleVector &weights) {
      PRECONDITION(points.size() == weights.size(), "");
      double res = 0.0;
      RDGeom::Point3DConstPtrVect_CI pti;
      const double *wData = weights.getData();
      unsigned int i = 0;
      for (pti = points.begin(); pti != points.end(); pti++) {
        res += (wData[i]*((*pti)->lengthSq()));
        i++;
      }
      return res;
    }

    double _sumOfWeights(const DoubleVector &weights) {
      const double *wData = weights.getData();
      double res = 0.0;
      for (unsigned int i = 0; i < weights.size(); i++) {
        CHECK_INVARIANT(wData[i] > 0.0, "Negative weight specified for a point");
        res += wData[i];
      }
      return res;
    }

    void _computeCovarianceMat(const RDGeom::Point3DConstPtrVect &refPoints,
                               const RDGeom::Point3DConstPtrVect &probePoints,
                               const DoubleVector &weights,
                               double covMat[3][3]) {
      unsigned int i, j;
      for (i = 0; i < 3; i++) {
        for (j=0; j < 3; j++) {
          covMat[i][j] = 0.0;
        }
      }
      unsigned int npt = refPoints.size();
      CHECK_INVARIANT(npt == probePoints.size(), "Number of points mismatch");
      CHECK_INVARIANT(npt == weights.size(), "Number of points and number of weights do not match");
      const double *wData = weights.getData();

      const RDGeom::Point3D *rpt, *ppt;
      double w;
      for (i = 0; i < npt; i++) {
        rpt = refPoints[i];
        ppt = probePoints[i];
        w = wData[i];

        covMat[0][0] += w*(ppt->x)*(rpt->x);
        covMat[0][1] += w*(ppt->x)*(rpt->y);
        covMat[0][2] += w*(ppt->x)*(rpt->z);

        covMat[1][0] += w*(ppt->y)*(rpt->x);
        covMat[1][1] += w*(ppt->y)*(rpt->y);
        covMat[1][2] += w*(ppt->y)*(rpt->z);

        covMat[2][0] += w*(ppt->z)*(rpt->x);
        covMat[2][1] += w*(ppt->z)*(rpt->y);
        covMat[2][2] += w*(ppt->z)*(rpt->z);
      }
    }

    void _covertCovMatToQuad(const double covMat[3][3],
                             const RDGeom::Point3D &rptSum, const RDGeom::Point3D &pptSum,
                             double wtsSum, double quad[4][4]) {
      double PxRx, PxRy, PxRz;
      double PyRx, PyRy, PyRz;
      double PzRx, PzRy, PzRz;
      double temp;

      temp = pptSum.x/wtsSum;
      PxRx = covMat[0][0] - temp*rptSum.x;
      PxRy = covMat[0][1] - temp*rptSum.y;
      PxRz = covMat[0][2] - temp*rptSum.z;

      temp = pptSum.y/wtsSum;
      PyRx = covMat[1][0] - temp*rptSum.x;
      PyRy = covMat[1][1] - temp*rptSum.y;
      PyRz = covMat[1][2] - temp*rptSum.z;

      temp = pptSum.z/wtsSum;
      PzRx = covMat[2][0] - temp*rptSum.x;
      PzRy = covMat[2][1] - temp*rptSum.y;
      PzRz = covMat[2][2] - temp*rptSum.z;

      quad[0][0] = -2.0*(PxRx + PyRy + PzRz);
      quad[1][1] = -2.0*(PxRx - PyRy - PzRz);
      quad[2][2] = -2.0*(PyRy - PzRz - PxRx);
      quad[3][3] = -2.0*(PzRz - PxRx - PyRy);

      quad[0][1] = quad[1][0] = 2.0*(PyRz - PzRy);
      quad[0][2] = quad[2][0] = 2.0*(PzRx - PxRz);
      quad[0][3] = quad[3][0] = 2.0*(PxRy - PyRx);
      quad[1][2] = quad[2][1] = -2.0*(PxRy + PyRx);
      quad[1][3] = quad[3][1] = -2.0*(PzRx + PxRz);
      quad[2][3] = quad[3][2] = -2.0*(PyRz + PzRy);
    }

    //! Obtain the eigen vectors and eigen values
    /*!
      \param quad        4x4 matrix of interest
      \param eigenVals   storage for eigen values
      \param eigenVecs   storage for eigen vectors
      \param maxIter     max number of iterations

      <b>Reference:<\b>
      This is essentailly a copy of the jacobi routine taken from the program
      quatfit.c available from the Computational Chemistry Archives.
      http://www.ccl.net/cca/software/SOURCES/C/quaternion-mol-fit/index.shtml
      E-mail jkl@osc.edu for details.
      It was written by:

      David J. Heisterberg
      The Ohio Supercomputer Center
      1224 Kinnear Rd.
      Columbus, OH  43212-1163
      (614)292-6036
      djh@osc.edu    djh@ohstpy.bitnet    ohstpy::djh
      Copyright: Ohio Supercomputer Center, David J. Heisterberg, 1990.
      The program can be copied and distributed freely, provided that
      this copyright in not removed. You may acknowledge the use of the
      program in published material as:
      David J. Heisterberg, 1990, unpublished results.

      Also see page 463 in Numerical Recipes in C (second edition)
    */

    unsigned int jacobi (double quad[4][4], double eigenVals[4], double eigenVecs[4][4],
                unsigned int maxIter) {
      double offDiagNorm, diagNorm;
      double b, dma, q, t, c, s;
      double atemp, vtemp, dtemp;
      int i, j, k;
      unsigned int l;

      // initialize the eigen vector to Identity
      for (j = 0; j <= 3; j++) {
        for (i = 0; i <= 3; i++) eigenVecs[i][j] = 0.0;
        eigenVecs[j][j] = 1.0;
        eigenVals[j] = quad[j][j];
      }

      for (l = 0; l < maxIter; l++) {
        diagNorm = 0.0;
        offDiagNorm = 0.0;
        for (j = 0; j <= 3; j++) {
          diagNorm += fabs(eigenVals[j]);
          for (i = 0; i <= j - 1; i++) {
            offDiagNorm += fabs(quad[i][j]);
          }
        }
        if((offDiagNorm/diagNorm) <= TOLERANCE)
          goto Exit_now;
        for (j = 1; j <= 3; j++) {
          for (i = 0; i <= j - 1; i++) {
            b = quad[i][j];
            if(fabs(b) > 0.0) {
              dma = eigenVals[j] - eigenVals[i];
              if((fabs(dma) + fabs(b)) <=  fabs(dma)) {
                t = b / dma;
              }
              else {
                q = 0.5 * dma / b;
                t = 1.0/(fabs(q) + sqrt(1.0+q*q));
                if(q < 0.0) {
                  t = -t;
                }
              }
              c = 1.0/sqrt(t * t + 1.0);
              s = t * c;
              quad[i][j] = 0.0;
              for (k = 0; k <= i-1; k++) {
                atemp = c * quad[k][i] - s * quad[k][j];
                quad[k][j] = s * quad[k][i] + c * quad[k][j];
                quad[k][i] = atemp;
              }
              for (k = i+1; k <= j-1; k++) {
                atemp = c * quad[i][k] - s * quad[k][j];
                quad[k][j] = s * quad[i][k] + c * quad[k][j];
                quad[i][k] = atemp;
              }
              for (k = j+1; k <= 3; k++) {
                atemp = c * quad[i][k] - s * quad[j][k];
                quad[j][k] = s * quad[i][k] + c * quad[j][k];
                quad[i][k] = atemp;
              }
              for (k = 0; k <= 3; k++) {
                vtemp = c * eigenVecs[k][i] - s * eigenVecs[k][j];
                eigenVecs[k][j] = s * eigenVecs[k][i] + c * eigenVecs[k][j];
                eigenVecs[k][i] = vtemp;
              }
              dtemp = c*c*eigenVals[i] + s*s*eigenVals[j] - 2.0*c*s*b;
              eigenVals[j] = s*s*eigenVals[i] + c*c*eigenVals[j] +  2.0*c*s*b;
              eigenVals[i] = dtemp;
            }  /* end if */
          } /* end for i */
        } /* end for j */
      } /* end for l */

    Exit_now:

      for (j = 0; j <= 2; j++) {
        k = j;
        dtemp = eigenVals[k];
        for (i = j+1; i <= 3; i++) {
          if(eigenVals[i] < dtemp) {
            k = i;
            dtemp = eigenVals[k];
          }
        }

        if(k > j) {
          eigenVals[k] = eigenVals[j];
          eigenVals[j] = dtemp;
          for (i = 0; i <= 3; i++) {
            dtemp = eigenVecs[i][k];
            eigenVecs[i][k] = eigenVecs[i][j];
            eigenVecs[i][j] = dtemp;
          }
        }
      }
      return l+1;
    }

    void reflectCovMat(double covMat[3][3]) {
      unsigned int i, j;
      for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
          covMat[i][j] = -covMat[i][j];
        }
      }
    }

    double AlignPoints(const RDGeom::Point3DConstPtrVect &refPoints,
                       const RDGeom::Point3DConstPtrVect &probePoints,
                       RDGeom::Transform3D &trans,
                       const DoubleVector *weights, bool reflect,
                       unsigned int maxIterations) {
      unsigned int npt = refPoints.size();
      PRECONDITION(npt == probePoints.size(), "Mismatch in number of points");
      trans.setToIdentity();
      const DoubleVector *wts;
      double wtsSum;
      bool ownWts;
      if (weights) {
        PRECONDITION(npt == weights->size(), "Mismatch in number of points");
        wts = weights;
        wtsSum = _sumOfWeights(*wts);
        ownWts=false;
      } else {
        wts = new DoubleVector(npt, 1.0);
        wtsSum = static_cast<double>(npt);
        ownWts=true;
      }

      RDGeom::Point3D rptSum = _weightedSumOfPoints(refPoints, *wts);
      RDGeom::Point3D pptSum = _weightedSumOfPoints(probePoints, *wts);

      double rptSumLenSq = _weightedSumOfLenSq(refPoints, *wts);
      double pptSumLenSq = _weightedSumOfLenSq(probePoints, *wts);

      double covMat[3][3];

      // compute the co-variance matrix
      _computeCovarianceMat(refPoints, probePoints, *wts, covMat);
      if(ownWts) {
        delete wts;
        wts=0;
      }
      if (reflect) {
        rptSum *= -1.0;
        reflectCovMat(covMat);
      }

      // convert the covariance matrix to a 4x4 matrix that needs to be diagonalized
      double quad[4][4];
      _covertCovMatToQuad(covMat, rptSum, pptSum, wtsSum, quad);

      // get the eigenVecs and eigenVals for the matrix
      double eigenVecs[4][4], eigenVals[4];
      unsigned int numIter;
      numIter = jacobi(quad, eigenVals, eigenVecs, maxIterations);

      // get the quaternion
      double quater[4];
      quater[0] = eigenVecs[0][0];
      quater[1] = eigenVecs[1][0];
      quater[2] = eigenVecs[2][0];
      quater[3] = eigenVecs[3][0];

      trans.SetRotationFromQuaternion(quater);
      if (reflect) {
        // put the flip in the rotation matrix
        trans.Reflect();
      }
      // compute the SSR value
      double ssr = eigenVals[0] - (pptSum.lengthSq() + rptSum.lengthSq())/wtsSum
        + rptSumLenSq + pptSumLenSq;

      if ((ssr < 0.0) && (fabs(ssr) < TOLERANCE)) {
        ssr = 0.0;
      }
      if (reflect) {
        rptSum *= -1.0;
      }

      // set the translation
      trans.TransformPoint(pptSum);
      RDGeom::Point3D move = rptSum;
      move -= pptSum;
      move /= wtsSum;
      trans.SetTranslation(move);
      return ssr;
    }
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.
 */

// OpenGL ES 2.0 code
#include <stdint.h>
#include <jni.h>
#include <android/bitmap.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <string>
#include <vector>
#include <array>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "NativeBitmap.h"
#include "Texture.h"
#include "GLES2Lesson.h"
#include "NdkGlue.h"
#include "LightningStrategy.h"
#include "android_asset_operations.h"

std::string gVertexShader;
std::string gFragmentShader;
std::shared_ptr<odb::GLES2Lesson> gles2Lesson = nullptr;
std::vector<std::shared_ptr<odb::NativeBitmap>> textures;

odb::IntGameMap map;
odb::IntGameMap snapshot;
odb::IntGameMap splat;
odb::LightMap lightMap;

void loadShaders(JNIEnv *env, jobject &obj) {
    AAssetManager *asset_manager = AAssetManager_fromJava(env, obj);
    FILE *fd;
    fd = android_fopen("vertex.glsl", "r", asset_manager);
    gVertexShader = readToString(fd);
    fclose(fd);
    fd = android_fopen("fragment.glsl", "r", asset_manager);
    gFragmentShader = readToString(fd);
    fclose(fd);
}

bool setupGraphics(int w, int h) {
    gles2Lesson = std::make_shared<odb::GLES2Lesson>();
	gles2Lesson->setTexture(textures);
    return gles2Lesson->init(w, h, gVertexShader.c_str(), gFragmentShader.c_str());
}

void renderFrame() {
    if (gles2Lesson != nullptr && textures.size() > 0 ) {
	    gles2Lesson->render(map, snapshot, splat, lightMap);
    }
}

void shutdown() {
	gles2Lesson->shutdown();
	textures.clear();
    gles2Lesson = nullptr;
}

void tick() {
    if (gles2Lesson != nullptr) {
        gles2Lesson->tick();
    }
}

extern "C" {
JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onCreate(JNIEnv *env, void *reserved,
                                                                    jobject assetManager);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setCurrentCursorPosition(JNIEnv *env, jclass type, jfloat x, jfloat y);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setCameraPosition(JNIEnv *env, jclass type, jfloat x, jfloat y);

JNIEXPORT void JNICALL
    Java_br_odb_GL2JNILib_setTextures(JNIEnv *env, jclass type, jobjectArray bitmaps);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_toggleCloseupCamera(JNIEnv *env, jclass type);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onDestroy(JNIEnv *env, jobject obj);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_init(JNIEnv *env, jobject obj,
                                                                jint width, jint height);
JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_step(JNIEnv *env, jobject obj);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setMapWithSplatsAndActors(JNIEnv *env, jclass type, jintArray map_, jintArray actors_, jintArray splats_);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_tick(JNIEnv *env, jobject obj);

};

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onCreate(JNIEnv *env, void *reserved,
                                                                    jobject assetManager) {
    loadShaders(env, assetManager);
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_init(JNIEnv *env, jobject obj,
                                                                jint width, jint height) {
    setupGraphics(width, height);
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_step(JNIEnv *env, jobject obj) {
	renderFrame();
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_tick(JNIEnv *env, jobject obj) {
    tick();
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onDestroy(JNIEnv *env, jobject obj) {
    shutdown();
}

std::shared_ptr<odb::NativeBitmap> makeNativeBitmapFromJObject(JNIEnv *env, jobject bitmap) {

	void *addr;
	AndroidBitmapInfo info;
	int errorCode;

	if ((errorCode = AndroidBitmap_lockPixels(env, bitmap, &addr)) != 0) {
		LOGI("error %d", errorCode);
	}

	if ((errorCode = AndroidBitmap_getInfo(env, bitmap, &info)) != 0) {
		LOGI("error %d", errorCode);
	}

	LOGI("bitmap info: %d wide, %d tall, %d ints per pixel", info.width, info.height, info.format);

	long size = info.width * info.height * info.format;
	int *pixels = new int[size];
	memcpy(pixels, addr, size * sizeof(int));
	auto toReturn = std::make_shared<odb::NativeBitmap>(info.width, info.height, pixels);

	if ((errorCode = AndroidBitmap_unlockPixels(env, bitmap)) != 0) {
		LOGI("error %d", errorCode);
	}

	return toReturn;
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setTextures(JNIEnv *env, jclass type, jobjectArray bitmaps) {
	int length = env->GetArrayLength( bitmaps );
	textures.clear();
	for ( int c = 0; c < length; ++c ) {
		textures.push_back( makeNativeBitmapFromJObject( env, env->GetObjectArrayElement( bitmaps, c ) ) );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setCameraPosition(JNIEnv *env, jclass type, jfloat x, jfloat y) {
	if (gles2Lesson != nullptr) {
		gles2Lesson->setCameraPosition( x, y );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setMapWithSplatsAndActors(JNIEnv *env, jclass type, jintArray map_, jintArray actors_, jintArray splats_) {
	jint *level = env->GetIntArrayElements(map_, NULL);
	jint *actors = env->GetIntArrayElements(actors_, NULL);
	jint *splats = env->GetIntArrayElements(splats_, NULL);

	int position;
	for ( int y = 0; y < 20; ++y ) {
		for ( int x = 0; x < 20; ++x ) {
			position = ( y * 20 ) + x;
			map[ y ][ x ] = (odb::ETextures) level[ position ];
			snapshot[ y ][ x ] = (odb::ETextures) actors[ position ];
			splat[ y ][ x ] = (odb::ETextures) splats[ position ];
			lightMap[ y ][ x ] = 0;
		}
	}

	for ( int y = 0; y < 20; ++y ) {
		for (int x = 0; x < 20; ++x) {
			if ( map[ y ][ x ] == odb::ETextures::BricksCandles ) {
				odb::LightningStrategy::castLight( lightMap, 128, map, x, y);
			}

			if ( snapshot[ y ][ x ] != odb::ETextures::None ) {
				odb::LightningStrategy::castLight( lightMap, 16, map, x, y);
			}

		}
	}

	env->ReleaseIntArrayElements(map_, level, 0);
	env->ReleaseIntArrayElements(actors_, actors, 0);
	env->ReleaseIntArrayElements(splats_, splats, 0);
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setCurrentCursorPosition(JNIEnv *env, jclass type, jfloat x, jfloat y) {

	if (gles2Lesson != nullptr) {
		gles2Lesson->setCursorAt( x, y );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_toggleCloseupCamera(JNIEnv *env, jclass type) {

	if (gles2Lesson != nullptr) {
		gles2Lesson->toggleCloseUpCamera();
	}
}<commit_msg>Add static lightning cache<commit_after>/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.
 */

// OpenGL ES 2.0 code
#include <stdint.h>
#include <jni.h>
#include <android/bitmap.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <string>
#include <vector>
#include <array>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "NativeBitmap.h"
#include "Texture.h"
#include "GLES2Lesson.h"
#include "NdkGlue.h"
#include "LightningStrategy.h"
#include "android_asset_operations.h"

std::string gVertexShader;
std::string gFragmentShader;
std::shared_ptr<odb::GLES2Lesson> gles2Lesson = nullptr;
std::vector<std::shared_ptr<odb::NativeBitmap>> textures;

odb::IntGameMap map;
odb::IntGameMap snapshot;
odb::IntGameMap splat;
odb::LightMap lightMap;

bool hasCache;
odb::LightMap lightMapCache;

void loadShaders(JNIEnv *env, jobject &obj) {
    AAssetManager *asset_manager = AAssetManager_fromJava(env, obj);
    FILE *fd;
    fd = android_fopen("vertex.glsl", "r", asset_manager);
    gVertexShader = readToString(fd);
    fclose(fd);
    fd = android_fopen("fragment.glsl", "r", asset_manager);
    gFragmentShader = readToString(fd);
    fclose(fd);
}

bool setupGraphics(int w, int h) {
    gles2Lesson = std::make_shared<odb::GLES2Lesson>();
	gles2Lesson->setTexture(textures);
    return gles2Lesson->init(w, h, gVertexShader.c_str(), gFragmentShader.c_str());
}

void renderFrame() {
    if (gles2Lesson != nullptr && textures.size() > 0 ) {
	    gles2Lesson->render(map, snapshot, splat, lightMap);
    }
}

void shutdown() {
	gles2Lesson->shutdown();
	textures.clear();
    gles2Lesson = nullptr;
}

void tick() {
    if (gles2Lesson != nullptr) {
        gles2Lesson->tick();
    }
}

extern "C" {
JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onCreate(JNIEnv *env, void *reserved,
                                                                    jobject assetManager);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setCurrentCursorPosition(JNIEnv *env, jclass type, jfloat x, jfloat y);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setCameraPosition(JNIEnv *env, jclass type, jfloat x, jfloat y);

JNIEXPORT void JNICALL
    Java_br_odb_GL2JNILib_setTextures(JNIEnv *env, jclass type, jobjectArray bitmaps);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_toggleCloseupCamera(JNIEnv *env, jclass type);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onDestroy(JNIEnv *env, jobject obj);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_init(JNIEnv *env, jobject obj,
                                                                jint width, jint height);
JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_step(JNIEnv *env, jobject obj);

JNIEXPORT void JNICALL
		Java_br_odb_GL2JNILib_setMapWithSplatsAndActors(JNIEnv *env, jclass type, jintArray map_, jintArray actors_, jintArray splats_);

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_tick(JNIEnv *env, jobject obj);

};

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onCreate(JNIEnv *env, void *reserved,
                                                                    jobject assetManager) {
    loadShaders(env, assetManager);
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_init(JNIEnv *env, jobject obj,
                                                                jint width, jint height) {
    setupGraphics(width, height);
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_step(JNIEnv *env, jobject obj) {
	renderFrame();
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_tick(JNIEnv *env, jobject obj) {
    tick();
}

JNIEXPORT void JNICALL Java_br_odb_GL2JNILib_onDestroy(JNIEnv *env, jobject obj) {
    shutdown();
}

std::shared_ptr<odb::NativeBitmap> makeNativeBitmapFromJObject(JNIEnv *env, jobject bitmap) {

	void *addr;
	AndroidBitmapInfo info;
	int errorCode;

	if ((errorCode = AndroidBitmap_lockPixels(env, bitmap, &addr)) != 0) {
		LOGI("error %d", errorCode);
	}

	if ((errorCode = AndroidBitmap_getInfo(env, bitmap, &info)) != 0) {
		LOGI("error %d", errorCode);
	}

	LOGI("bitmap info: %d wide, %d tall, %d ints per pixel", info.width, info.height, info.format);

	long size = info.width * info.height * info.format;
	int *pixels = new int[size];
	memcpy(pixels, addr, size * sizeof(int));
	auto toReturn = std::make_shared<odb::NativeBitmap>(info.width, info.height, pixels);

	if ((errorCode = AndroidBitmap_unlockPixels(env, bitmap)) != 0) {
		LOGI("error %d", errorCode);
	}

	return toReturn;
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setTextures(JNIEnv *env, jclass type, jobjectArray bitmaps) {
	int length = env->GetArrayLength( bitmaps );
	textures.clear();
	for ( int c = 0; c < length; ++c ) {
		textures.push_back( makeNativeBitmapFromJObject( env, env->GetObjectArrayElement( bitmaps, c ) ) );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setCameraPosition(JNIEnv *env, jclass type, jfloat x, jfloat y) {
	if (gles2Lesson != nullptr) {
		gles2Lesson->setCameraPosition( x, y );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setMapWithSplatsAndActors(JNIEnv *env, jclass type, jintArray map_, jintArray actors_, jintArray splats_) {
	jint *level = env->GetIntArrayElements(map_, NULL);
	jint *actors = env->GetIntArrayElements(actors_, NULL);
	jint *splats = env->GetIntArrayElements(splats_, NULL);

	int position;
	for ( int y = 0; y < 20; ++y ) {
		for ( int x = 0; x < 20; ++x ) {
			position = ( y * 20 ) + x;
			map[ y ][ x ] = (odb::ETextures) level[ position ];
			snapshot[ y ][ x ] = (odb::ETextures) actors[ position ];
			splat[ y ][ x ] = (odb::ETextures) splats[ position ];
			lightMap[ y ][ x ] = lightMapCache[ y ][ x ];
		}
	}

	for ( int y = 0; y < 20; ++y ) {
		for (int x = 0; x < 20; ++x) {

			if ( map[ y ][ x ] == odb::ETextures::BricksCandles ) {

				if ( !hasCache ) {
					odb::LightningStrategy::castLight( lightMapCache, 128, map, x, y);
					odb::LightningStrategy::castLight( lightMap, 128, map, x, y);
				}
			}

			if ( snapshot[ y ][ x ] != odb::ETextures::None ) {
				odb::LightningStrategy::castLight( lightMap, 16, map, x, y);
			}

		}
	}

	hasCache = true;

	env->ReleaseIntArrayElements(map_, level, 0);
	env->ReleaseIntArrayElements(actors_, actors, 0);
	env->ReleaseIntArrayElements(splats_, splats, 0);
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_setCurrentCursorPosition(JNIEnv *env, jclass type, jfloat x, jfloat y) {

	if (gles2Lesson != nullptr) {
		gles2Lesson->setCursorAt( x, y );
	}
}

JNIEXPORT void JNICALL
Java_br_odb_GL2JNILib_toggleCloseupCamera(JNIEnv *env, jclass type) {

	if (gles2Lesson != nullptr) {
		gles2Lesson->toggleCloseUpCamera();
	}
}<|endoftext|>


<commit_before>// Alexis Giraudet
// Théo Cesbron

#ifndef PARSER_DICTIONNAIRE_HPP
#define PARSER_DICTIONNAIRE_HPP

#include <algorithm>
#include <fstream>
#include "hash_dictionnaire.hpp"
#include "tree_dictionnaire.hpp"

using namespace std;

enum type_dictionnaire {HASH_DICTIONNAIRE, TREE_DICTIONNAIRE, UNKNOWN};

void help();
int main(int argc, char *argv[]);

class parser_dictionnaire
{
    protected:
        abstract_dictionnaire<int>* _dict;
        string* _words;
        int* _frequencies;
        int _size;

    public:
        parser_dictionnaire(type_dictionnaire type);
        ~parser_dictionnaire();
        static bool is_punctuation(char c);
        void most_frequent(int n=10);
        int parse(ifstream& file);
        void print() const;

    protected:
        void add_word(const string& word);
        void sort();
};

parser_dictionnaire::parser_dictionnaire(type_dictionnaire type): _dict(0), _words(0), _frequencies(0), _size(0)
{
    switch(type)
    {
        case HASH_DICTIONNAIRE: _dict = new hash_dictionnaire<int>();
            break;
        case TREE_DICTIONNAIRE: _dict = new tree_dictionnaire<int>();
            break;
        case UNKNOWN: throw exception();
            break;
    }
}

parser_dictionnaire::~parser_dictionnaire()
{
    delete _dict;
    delete[] _words;
    delete[] _frequencies;
}

void parser_dictionnaire::add_word(const string& word)
{
    try
    {
        (*_dict).associerMot(word,(*_dict).valeurAssociee(word)+1);
    }
    catch(exception& e)
    {
        (*_dict).ajouterMot(word,1);
    }
}

bool parser_dictionnaire::is_punctuation(char c)
{
    return (c == '\n') || (c == ' ') || (c == '.') || (c == '?') || (c == '!') || (c == ',') || (c == ';') || (c == ':') || (c == '(') || (c == ')') || (c == '[') || (c == ']') /*|| (c == '«') || (c == '»')*/ || (c == '-');
}

void parser_dictionnaire::most_frequent(int n)
{
    sort();
    cout << "Most frequent words:" << endl;
    for(int i=0; (i<_size) && (i<n); i++)
    {
        cout << i+1 << ") " << _words[i] << " (" << _frequencies[i] << ")" << endl;
    }
}

int parser_dictionnaire::parse(ifstream& file)
{
    string word;
    word.clear();
    while(file.good())
    {
        char c(file.get());
        if(file.good())
        {
            if(is_punctuation(c))
            {
                if(!word.empty())
                {
                    transform(word.begin(),word.end(),word.begin(),::tolower);
                    add_word(word);
                    word.clear();
                }
            }
            else
            {
                word.push_back(c);
            }
        }
        else
        {
            if(!word.empty())
            {
                add_word(word);
            }
        }
    }
    file.close();
    triplet<string*,int*,int> tr = (*_dict).to_array();
    _words = tr.first;
    _frequencies = tr.second;
    _size = tr.third;
    return _size;
}

void parser_dictionnaire::print() const
{
    cout << *_dict;
}

void parser_dictionnaire::sort()
{
    for(int i=0; i<_size; i++)
    {
        for(int j=0; j<_size-1; j++)
        {
            if(_frequencies[j] < _frequencies[j+1])
            {
                pair<string,int> tmp(_words[j],_frequencies[j]);
                _words[j] = _words[j+1];
                _frequencies[j] = _frequencies[j+1];
                _words[j+1] = tmp.first;
                _frequencies[j+1] = tmp.second;
            }
        }
    }
}

int main(int argc, char *argv[])
{
    if(argc<2)
    {
        cout << "Error: todo" << endl;
        return 1;
    }

    ifstream file;
    type_dictionnaire type(UNKNOWN);
    bool print(false);
    bool most_frequent(false);

    for(int i=1; i<argc; i++)
    {
        string arg(argv[i]);
        if(argv[i][0] == '-')
        {
            if(arg == "-tree")
            {
                type = TREE_DICTIONNAIRE;
            }
            else if(arg == "-hash")
            {
                type = HASH_DICTIONNAIRE;
            }
            else if(arg == "-print")
            {
                print = true;
            }
            else if(arg == "-most-frequent")
            {
                most_frequent = true;
            }
            else if(arg == "-help")
            {
                help();
                return 0;
            }
            else
            {
                cout << "Error: todo" << endl;
                return 1;
            }
        }
        else
        {
            if(file.is_open())
            {
                cout << "Warning: todo" << endl;
            }
            else
            {
                file.open(arg);
            }
        }
    }

    if(type == UNKNOWN)
    {
        cout << "Error: todo" << endl;
        return 1;
    }
    if(!file.is_open())
    {
        cout << "Error: todo" << endl;
        return 1;
    }

    parser_dictionnaire parser(type);
    cout << "Words read: " << parser.parse(file) << endl;
    if(print)
    {
        parser.print();
    }
    if(most_frequent)
    {
        parser.most_frequent();
    }

    return 0;
}

void help()
{
    cout << "todo" << endl;
}

#endif
<commit_msg>more verbose messages<commit_after>// Alexis Giraudet
// Théo Cesbron

#ifndef PARSER_DICTIONNAIRE_HPP
#define PARSER_DICTIONNAIRE_HPP

#include <algorithm>
#include <fstream>
#include "hash_dictionnaire.hpp"
#include "tree_dictionnaire.hpp"

using namespace std;

enum type_dictionnaire {HASH_DICTIONNAIRE, TREE_DICTIONNAIRE, UNKNOWN};

void help();
int main(int argc, char *argv[]);

class parser_dictionnaire
{
    protected:
        abstract_dictionnaire<int>* _dict;
        string* _words;
        int* _frequencies;
        int _size;

    public:
        parser_dictionnaire(type_dictionnaire type);
        ~parser_dictionnaire();
        static bool is_punctuation(char c);
        void most_frequent(int n=10);
        int parse(ifstream& file);
        void print() const;

    protected:
        void add_word(const string& word);
        void sort();
};

parser_dictionnaire::parser_dictionnaire(type_dictionnaire type): _dict(0), _words(0), _frequencies(0), _size(0)
{
    switch(type)
    {
        case HASH_DICTIONNAIRE: _dict = new hash_dictionnaire<int>();
            break;
        case TREE_DICTIONNAIRE: _dict = new tree_dictionnaire<int>();
            break;
        case UNKNOWN: throw exception();
            break;
    }
}

parser_dictionnaire::~parser_dictionnaire()
{
    delete _dict;
    delete[] _words;
    delete[] _frequencies;
}

void parser_dictionnaire::add_word(const string& word)
{
    try
    {
        (*_dict).associerMot(word,(*_dict).valeurAssociee(word)+1);
    }
    catch(exception& e)
    {
        (*_dict).ajouterMot(word,1);
    }
}

bool parser_dictionnaire::is_punctuation(char c)
{
    return (c == '\n') || (c == ' ') || (c == '.') || (c == '?') || (c == '!') || (c == ',') || (c == ';') || (c == ':') || (c == '(') || (c == ')') || (c == '[') || (c == ']') /*|| (c == '«') || (c == '»')*/ || (c == '-');
}

void parser_dictionnaire::most_frequent(int n)
{
    sort();
    cout << "Most frequent words:" << endl;
    for(int i=0; (i<_size) && (i<n); i++)
    {
        cout << i+1 << ") " << _words[i] << " (" << _frequencies[i] << ")" << endl;
    }
}

int parser_dictionnaire::parse(ifstream& file)
{
    string word;
    word.clear();
    while(file.good())
    {
        char c(file.get());
        if(file.good())
        {
            if(is_punctuation(c))
            {
                if(!word.empty())
                {
                    transform(word.begin(),word.end(),word.begin(),::tolower);
                    add_word(word);
                    word.clear();
                }
            }
            else
            {
                word.push_back(c);
            }
        }
        else
        {
            if(!word.empty())
            {
                add_word(word);
            }
        }
    }
    file.close();
    triplet<string*,int*,int> tr = (*_dict).to_array();
    _words = tr.first;
    _frequencies = tr.second;
    _size = tr.third;
    return _size;
}

void parser_dictionnaire::print() const
{
    cout << *_dict;
}

void parser_dictionnaire::sort()
{
    for(int i=0; i<_size; i++)
    {
        for(int j=0; j<_size-1; j++)
        {
            if(_frequencies[j] < _frequencies[j+1])
            {
                pair<string,int> tmp(_words[j],_frequencies[j]);
                _words[j] = _words[j+1];
                _frequencies[j] = _frequencies[j+1];
                _words[j+1] = tmp.first;
                _frequencies[j+1] = tmp.second;
            }
        }
    }
}

int main(int argc, char *argv[])
{
    if(argc<2)
    {
        cout << "Utilisation : parser [-hash | -tree]  [OPTIONS] [FILE]" << endl;
        cout << "Saisissez « parse -help » pour plus d'informations." << endl;
        return 1;
    }

    ifstream file;
    type_dictionnaire type(UNKNOWN);
    bool print(false);
    bool most_frequent(false);

    for(int i=1; i<argc; i++)
    {
        string arg(argv[i]);
        if(argv[i][0] == '-')
        {
            if(arg == "-tree")
            {
                type = TREE_DICTIONNAIRE;
            }
            else if(arg == "-hash")
            {
                type = HASH_DICTIONNAIRE;
            }
            else if(arg == "-print")
            {
                print = true;
            }
            else if(arg == "-most-frequent")
            {
                most_frequent = true;
            }
            else if(arg == "-help")
            {
                help();
                return 0;
            }
            else
            {
                cout << "parse: option invalide - '" << arg <<"'" << endl;
                cout << "Saisissez « parse -help » pour plus d'informations." << endl;

                return 1;
            }
        }
        else
        {
            if(file.is_open())
            {
                cout << "parse: indiquez un seul fichier à charger" << endl;
                cout << "Saisissez « parse -help » pour plus d'informations." << endl;
                return 0;
            }
            else
            {
                file.open(arg);
            }
        }
    }

    if(type == UNKNOWN)
    {
        cout << "parse: structure de dictionnaire inconnue" << endl;
        cout << "Saisissez « parse -help » pour plus d'informations." << endl;
        return 1;
    }
    if(!file.is_open())
    {
        cout << "parse: impossible d'ouvrir le fichier" << endl;
        cout << "Saisissez « parse -help » pour plus d'informations." << endl;
        return 1;
    }

    parser_dictionnaire parser(type);
    cout << "Mots chargés: " << parser.parse(file) << endl;
    if(print)
    {
        parser.print();
    }
    if(most_frequent)
    {
        parser.most_frequent();
    }

    return 0;
}

void help()
{
    cout << "Utilisation : parser [-hash | -tree]  [OPTIONS] [FILE]" << endl;
    cout << "Parcours le fichier passé en paramètre et charge les mots dans la structure de dictionnaire indiquée." << endl << endl;
    cout << "-hash             utilise la classe hash_dictionnaire" << endl;
    cout << "-tree             utilise la classe tree_dictionnaire" << endl;
    cout << "-print            affiche le contenu du dictionnaire" << endl;
    cout << "-most-frequent    affiche les dix mots les plus fréquents" << endl;
    cout << "-help             affiche l'aide" << endl;
}

#endif
<|endoftext|>


<commit_before>#include "configuration.h"

#include <string>
#include <sstream>
#include <fstream>

#include "../ext/json/json.hpp"
using json = nlohmann::json;
using namespace std::string_literals;

pichi::Configuration::Configuration(const std::string& filename)
  : filename_{filename}
{
  std::ifstream fs{filename_};
  json settings;

  if (fs.is_open()) {
    std::stringstream ss;
    ss << fs.rdbuf();
    fs.close();
    settings = json::parse(ss.str());
  }

  auto get = [&settings](const std::string& key, auto def) -> decltype(def) {
    if (settings.count(key)) {
      return settings[key];
    }
    return def;
  };

  gnss_port = get("gnss_port", "/dev/ttyS0"s);
  gnss_port_rate = get("gnss_port_rate", 9600);

  trans_ip = get("trans_ip", "192.168.0.1"s);
  trans_port = get("trans_port", 30001);

  recv_ip = get("recv_ip", "192.168.0.1"s);
  recv_port = get("recv_port", 30001);
  recv_log = get("recv_log", true);
  if (get("recv_log_format", "short"s) == "short")
    recv_log_format = LogFormat::Short;
  else
    recv_log_format = LogFormat::Full;

  log_csv = get("log_csv", true);
  log_gpx = get("log_gpx", true);
  log_csv_force_1hz = get("log_csv_force_1hz", false);
  log_gpx_force_1hz = get("log_gpx_force_1hz", true);
}

void pichi::Configuration::save_to_file() const
{
  json settings;

  settings["gnss_port"] = gnss_port;
  settings["gnss_port_rate"] = gnss_port_rate;

  settings["trans_ip"] = trans_ip;
  settings["trans_port"] = trans_port;

  settings["recv_ip"] = recv_ip;
  settings["recv_port"] = recv_port;
  settings["recv_log"] = recv_log;
  switch (recv_log_format) {
    case LogFormat::Full: settings["recv_log_format"] = "full"s; break;
    case LogFormat::Short: settings["recv_log_format"] = "short"s; break;
  }

  settings["log_csv"] = log_csv;
  settings["log_gpx"] = log_gpx;
  settings["log_csv_force_1hz"] = log_csv_force_1hz;
  settings["log_gpx_force_1hz"] = log_gpx_force_1hz;

  std::ofstream fs{filename_};
  if (fs.is_open()) {
    fs << settings.dump(2);
  }
}
<commit_msg>Added missing device_id field<commit_after>#include "configuration.h"

#include <string>
#include <sstream>
#include <fstream>

#include "../ext/json/json.hpp"
using json = nlohmann::json;
using namespace std::string_literals;

pichi::Configuration::Configuration(const std::string& filename)
  : filename_{filename}
{
  std::ifstream fs{filename_};
  json settings;

  if (fs.is_open()) {
    std::stringstream ss;
    ss << fs.rdbuf();
    fs.close();
    settings = json::parse(ss.str());
  }

  auto get = [&settings](const std::string& key, auto def) -> decltype(def) {
    if (settings.count(key)) {
      return settings[key];
    }
    return def;
  };

  device_id = get("device_id", 1);

  gnss_port = get("gnss_port", "/dev/ttyS0"s);
  gnss_port_rate = get("gnss_port_rate", 9600);

  trans_ip = get("trans_ip", "192.168.0.1"s);
  trans_port = get("trans_port", 30001);

  recv_ip = get("recv_ip", "192.168.0.1"s);
  recv_port = get("recv_port", 30001);
  recv_log = get("recv_log", true);
  if (get("recv_log_format", "short"s) == "short")
    recv_log_format = LogFormat::Short;
  else
    recv_log_format = LogFormat::Full;

  log_csv = get("log_csv", true);
  log_gpx = get("log_gpx", true);
  log_csv_force_1hz = get("log_csv_force_1hz", false);
  log_gpx_force_1hz = get("log_gpx_force_1hz", true);
}

void pichi::Configuration::save_to_file() const
{
  json settings;

  settings["device_id"] = device_id;

  settings["gnss_port"] = gnss_port;
  settings["gnss_port_rate"] = gnss_port_rate;

  settings["trans_ip"] = trans_ip;
  settings["trans_port"] = trans_port;

  settings["recv_ip"] = recv_ip;
  settings["recv_port"] = recv_port;
  settings["recv_log"] = recv_log;
  switch (recv_log_format) {
    case LogFormat::Full: settings["recv_log_format"] = "full"s; break;
    case LogFormat::Short: settings["recv_log_format"] = "short"s; break;
  }

  settings["log_csv"] = log_csv;
  settings["log_gpx"] = log_gpx;
  settings["log_csv_force_1hz"] = log_csv_force_1hz;
  settings["log_gpx_force_1hz"] = log_gpx_force_1hz;

  std::ofstream fs{filename_};
  if (fs.is_open()) {
    fs << settings.dump(2);
  }
}
<|endoftext|>