<commit_before>#pragma once

#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>

// forward for polyfill::make_ostream_joiner
template <typename Stream, typename V1, typename V2> Stream& operator << (Stream& out, const std::pair<V1, V2>& aPair);

#include "acmacs-base/iterator.hh"
#include "acmacs-base/sfinae.hh"

// ----------------------------------------------------------------------
// to work with std::copy, std::transform, operators << have to be declared in the namespace std

template <typename Stream, typename V1, typename V2> inline Stream& operator << (Stream& out, const std::pair<V1, V2>& aPair)
{
    return out << '(' << aPair.first << ", " << aPair.second << ')';
}

namespace stream_internal
{
    template <typename Stream, typename Iterator> inline Stream& write_to_stream(Stream& out, Iterator first, Iterator last, std::string prefix, std::string suffix, std::string separator)
    {
        out << prefix;
        std::copy(first, last, polyfill::make_ostream_joiner(out, separator));
        return out << suffix;
    }

    template <typename Stream, typename Collection, typename = std::enable_if<ad_sfinae::is_std_container<Collection>::value>>
                      inline Stream& write_to_stream(Stream& out, const Collection& aCollection, std::string prefix, std::string suffix, std::string separator)
    {
        return write_to_stream(out, std::begin(aCollection), std::end(aCollection), prefix, suffix, separator);
    }
}

// ----------------------------------------------------------------------

template <typename Stream, typename Value> inline Stream& operator << (Stream& out, const std::vector<Value>& aCollection)
{
    return stream_internal::write_to_stream(out, aCollection, "[", "]", ", ");
}

// ----------------------------------------------------------------------

template <typename Stream, typename Value> inline Stream& operator << (Stream& out, const std::set<Value>& aCollection)
{
    return stream_internal::write_to_stream(out, aCollection, "{", "}", ", ");
}

// ----------------------------------------------------------------------

template <typename Stream, typename Key, typename Value> inline Stream& operator << (Stream& out, const std::map<Key, Value>& aCollection)
{
    out << '{';
    std::transform(std::begin(aCollection), std::end(aCollection), polyfill::make_ostream_joiner(out, ", "), [](const auto& elt) { std::ostringstream os; os << '<' << elt.first << ">: <" << elt.second << '>'; return os.str(); });
    return out << '}';
}

// ----------------------------------------------------------------------

// template <typename Stream, typename Collection> class to_stream_t
// {
//  public:
//     using value_type = typename Collection::value_type;
//     using const_iterator = typename Collection::const_iterator;
//     using transformer_t = typename std::function<std::string(value_type)>;

//     inline to_stream_t(const_iterator first, const_iterator last, transformer_t transformer) : mFirst(first), mLast(last), mTransformer(transformer) {}

//     inline friend Stream& operator << (Stream& out, const to_stream_t<Stream, Collection>& converter)
//         {
//             if ((converter.mLast - converter.mFirst) > 1)
//                 std::transform(converter.mFirst, converter.mLast, std::ostream_iterator<std::string>(out, " "), converter.mTransformer);
//             else
//                 out << converter.mTransformer(*converter.mFirst);
//             return out;
//         }

//  private:
//     const_iterator mFirst, mLast;
//     transformer_t mTransformer;

// }; // class to_stream

// template <typename Stream, typename Collection> inline auto to_stream(const Collection& c, typename to_stream_t<Stream, Collection>::transformer_t transformer)
// {
//     return to_stream_t<Stream, Collection>(c.begin(), c.end(), transformer);
// }

// template <typename Stream, typename Collection> inline auto to_stream(const Collection& c)
// {
//     return to_stream_t<Stream, Collection>(c.begin(), c.end(), std::to_string);
// }

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>bug fix<commit_after>#pragma once

#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>

// forward for polyfill::make_ostream_joiner
template <typename Stream, typename V1, typename V2> Stream& operator << (Stream& out, const std::pair<V1, V2>& aPair);
template <typename Stream, typename Value> Stream& operator << (Stream& out, const std::vector<Value>& aCollection);

#include "acmacs-base/iterator.hh"
#include "acmacs-base/sfinae.hh"

// ----------------------------------------------------------------------
// to work with std::copy, std::transform, operators << have to be declared in the namespace std

template <typename Stream, typename V1, typename V2> inline Stream& operator << (Stream& out, const std::pair<V1, V2>& aPair)
{
    return out << '(' << aPair.first << ", " << aPair.second << ')';
}

namespace stream_internal
{
    template <typename Stream, typename Iterator> inline Stream& write_to_stream(Stream& out, Iterator first, Iterator last, std::string prefix, std::string suffix, std::string separator)
    {
        out << prefix;
        std::copy(first, last, polyfill::make_ostream_joiner(out, separator));
        return out << suffix;
    }

    template <typename Stream, typename Collection, typename = std::enable_if<ad_sfinae::is_std_container<Collection>::value>>
                      inline Stream& write_to_stream(Stream& out, const Collection& aCollection, std::string prefix, std::string suffix, std::string separator)
    {
        return write_to_stream(out, std::begin(aCollection), std::end(aCollection), prefix, suffix, separator);
    }
}

// ----------------------------------------------------------------------

template <typename Stream, typename Value> inline Stream& operator << (Stream& out, const std::vector<Value>& aCollection)
{
    return stream_internal::write_to_stream(out, aCollection, "[", "]", ", ");
}

// ----------------------------------------------------------------------

template <typename Stream, typename Value> inline Stream& operator << (Stream& out, const std::set<Value>& aCollection)
{
    return stream_internal::write_to_stream(out, aCollection, "{", "}", ", ");
}

// ----------------------------------------------------------------------

template <typename Stream, typename Key, typename Value> inline Stream& operator << (Stream& out, const std::map<Key, Value>& aCollection)
{
    out << '{';
    std::transform(std::begin(aCollection), std::end(aCollection), polyfill::make_ostream_joiner(out, ", "), [](const auto& elt) { std::ostringstream os; os << '<' << elt.first << ">: <" << elt.second << '>'; return os.str(); });
    return out << '}';
}

// ----------------------------------------------------------------------

// template <typename Stream, typename Collection> class to_stream_t
// {
//  public:
//     using value_type = typename Collection::value_type;
//     using const_iterator = typename Collection::const_iterator;
//     using transformer_t = typename std::function<std::string(value_type)>;

//     inline to_stream_t(const_iterator first, const_iterator last, transformer_t transformer) : mFirst(first), mLast(last), mTransformer(transformer) {}

//     inline friend Stream& operator << (Stream& out, const to_stream_t<Stream, Collection>& converter)
//         {
//             if ((converter.mLast - converter.mFirst) > 1)
//                 std::transform(converter.mFirst, converter.mLast, std::ostream_iterator<std::string>(out, " "), converter.mTransformer);
//             else
//                 out << converter.mTransformer(*converter.mFirst);
//             return out;
//         }

//  private:
//     const_iterator mFirst, mLast;
//     transformer_t mTransformer;

// }; // class to_stream

// template <typename Stream, typename Collection> inline auto to_stream(const Collection& c, typename to_stream_t<Stream, Collection>::transformer_t transformer)
// {
//     return to_stream_t<Stream, Collection>(c.begin(), c.end(), transformer);
// }

// template <typename Stream, typename Collection> inline auto to_stream(const Collection& c)
// {
//     return to_stream_t<Stream, Collection>(c.begin(), c.end(), std::to_string);
// }

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#ifndef __CCCALLCC_HPP__
#define __CCCALLCC_HPP__

#include <functional>
#include <memory>
#include <unistd.h>

#ifdef __GNUC__
#define NORETURN __attribute__((noreturn))
#else
#define NORETURN
#endif

template <typename T>
class cont {
public:
    typedef std::function<T (cont<T>)> call_cc_arg;

    static T call_cc(call_cc_arg f);

    void operator()(const T &x) NORETURN {
        m_impl_ptr->invoke(x);
    }

private:
    class impl {
    public:
        impl(int pipe)
            : m_pipe(pipe)
            { }

        ~impl() {
            close(m_pipe);
        }

        void invoke(const T &x) NORETURN {
            write(m_pipe, &x, sizeof(T));
            exit(0);
        }

    private:
        int m_pipe;
    };

    cont(int pipe)
        : m_impl_ptr(new impl(pipe))
        { }

    std::shared_ptr<impl> m_impl_ptr;
};

template <typename T>
T cont<T>::call_cc(call_cc_arg f) {
    int fd[2];
    pipe(fd);
    int read_fd  = fd[0];
    int write_fd = fd[1];

    pid_t pid = fork();
    if (pid) {
        // parent
        close(read_fd);
        return f( cont<T>(write_fd) );
    } else {
        // child
        close(write_fd);
        char buf[sizeof(T)];
        if (read(read_fd, buf, sizeof(T)) < ssize_t(sizeof(T)))
            exit(0);
        close(read_fd);
        return *reinterpret_cast<T*>(buf);
    }
}

template <typename T>
static inline T call_cc(typename cont<T>::call_cc_arg f) {
    return cont<T>::call_cc(f);
}

#endif // !defined(__CCCALLCC_HPP__)
<commit_msg>simplify<commit_after>#ifndef __CCCALLCC_HPP__
#define __CCCALLCC_HPP__

#include <functional>
#include <memory>
#include <unistd.h>

#ifdef __GNUC__
#define NORETURN __attribute__((noreturn))
#else
#define NORETURN
#endif

template <typename T>
class cont {
public:
    typedef std::function<T (cont<T>)> call_cc_arg;

    static T call_cc(call_cc_arg f);

    void operator()(const T &x) NORETURN {
        m_impl_ptr->invoke(x);
    }

private:
    class impl {
    public:
        impl(int pipe)
            : m_pipe(pipe)
            { }

        ~impl() {
            close(m_pipe);
        }

        void invoke(const T &x) NORETURN {
            write(m_pipe, &x, sizeof(T));
            exit(0);
        }

    private:
        int m_pipe;
    };

    cont(int pipe)
        : m_impl_ptr(new impl(pipe))
        { }

    std::shared_ptr<impl> m_impl_ptr;
};

template <typename T>
T cont<T>::call_cc(call_cc_arg f) {
    int fd[2];
    pipe(fd);
    int read_fd  = fd[0];
    int write_fd = fd[1];

    if (fork()) {
        // parent
        close(read_fd);
        return f( cont<T>(write_fd) );
    } else {
        // child
        close(write_fd);
        char buf[sizeof(T)];
        if (read(read_fd, buf, sizeof(T)) < ssize_t(sizeof(T)))
            exit(0);
        close(read_fd);
        return *reinterpret_cast<T*>(buf);
    }
}

template <typename T>
static inline T call_cc(typename cont<T>::call_cc_arg f) {
    return cont<T>::call_cc(f);
}

#endif // !defined(__CCCALLCC_HPP__)
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "vertex_index.h"

#include "vector_vector.h"
#include "fm_utils.h"
#include "fg_utils.h"
#include "crs_header.h"
#include "local_vec_store.h"

using namespace fm;

void read_data(char *data, size_t size, size_t num, off_t off, FILE *stream)
{
	int iret = fseek(stream, off, SEEK_SET);
	assert(iret == 0);
	size_t ret = fread(data, size, num, stream);
	assert(ret == num);
}

class adj2crs_apply_operate: public arr_apply_operate
{
public:
	adj2crs_apply_operate(): arr_apply_operate(0) {
	}
	virtual void run(const local_vec_store &in,
			local_vec_store &out) const;

	virtual const scalar_type &get_input_type() const {
		return get_scalar_type<char>();
	}
	virtual const scalar_type &get_output_type() const {
		return get_scalar_type<crs_idx_t>();
	}
};

void adj2crs_apply_operate::run(const local_vec_store &in,
		local_vec_store &out) const
{
	const fg::ext_mem_undirected_vertex *v
		= (const fg::ext_mem_undirected_vertex *) in.get_raw_arr();
	size_t num_edges = v->get_num_edges();
	out.resize(num_edges);
	for (size_t i = 0; i < num_edges; i++)
		out.set<crs_idx_t>(i, v->get_neighbor(i));
}

void export_crs(vector_vector::ptr adjs, const std::string &output_file)
{
	vector_vector::ptr col_idxs = vector_vector::cast(
			adjs->apply(adj2crs_apply_operate()));
	vector::ptr col_vec = col_idxs->cat();
	std::vector<crs_idx_t> offs(adjs->get_num_vecs() + 1);
	for (size_t i = 0; i < adjs->get_num_vecs(); i++) {
		offs[i + 1] = offs[i] + col_idxs->get_length(i);
	}

	FILE *f = fopen(output_file.c_str(), "w");
	if (f == NULL) {
		fprintf(stderr, "can't open %s: %s\n", output_file.c_str(), strerror(errno));
		exit(1);
	}

	// This is an adjacency matrix of a graph, so it has the same number of
	// rows and columns.
	crs_header header(adjs->get_num_vecs(), adjs->get_num_vecs(),
			col_vec->get_length());
	size_t ret = fwrite(&header, sizeof(header), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write header: %s\n", strerror(errno));
		exit(1);
	}

	ret = fwrite(offs.data(), offs.size() * sizeof(offs[0]), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write the row pointers: %s\n", strerror(errno));
		exit(1);
	}
	ret = fwrite(dynamic_cast<const detail::mem_vec_store &>(col_vec->get_data()).get_raw_arr(),
			col_vec->get_length() * col_vec->get_entry_size(), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write col idx: %s\n", strerror(errno));
		exit(1);
	}

	fclose(f);
}

int main(int argc, char *argv[])
{
	if (argc < 4) {
		fprintf(stderr, "el2crs graph_file index_file crs_file\n");
		return -1;
	}

	std::string graph_file = std::string(argv[1]);
	std::string index_file = std::string(argv[2]);
	std::string crs_file = std::string(argv[3]);

	fg::vertex_index::ptr vindex = fg::vertex_index::load(index_file);

	FILE *f = fopen(graph_file.c_str(), "r");
	if (f == NULL) {
		fprintf(stderr, "can't open %s: %s\n", graph_file.c_str(),
				strerror(errno));
		return -1;
	}

	size_t out_size = get_out_size(vindex);
	off_t out_off = get_out_off(vindex);
	detail::raw_data_array out_data(out_size);
	read_data(out_data.get_raw(), out_size, 1, out_off, f);
	std::vector<off_t> out_offs(vindex->get_num_vertices() + 1);
	init_out_offs(vindex, out_offs);
	vector_vector::ptr out_adjs = vector_vector::create(
			out_data, out_offs, get_scalar_type<char>());

	export_crs(out_adjs, crs_file);
	out_adjs = NULL;

	if (vindex->get_graph_header().is_directed_graph()) {
		std::string t_crs_file = std::string("t_") + crs_file;

		size_t in_size = get_in_size(vindex);
		off_t in_off = get_in_off(vindex);
		detail::raw_data_array in_data(in_size);
		read_data(in_data.get_raw(), in_size, 1, in_off, f);
		std::vector<off_t> in_offs(vindex->get_num_vertices() + 1);
		init_in_offs(vindex, in_offs);
		vector_vector::ptr in_adjs = vector_vector::create(
				in_data, in_offs, get_scalar_type<char>());

		export_crs(in_adjs, t_crs_file);
	}

	fclose(f);
}
<commit_msg>[Matrix]: fix a bug in al2crs.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "vertex_index.h"

#include "vector_vector.h"
#include "fm_utils.h"
#include "fg_utils.h"
#include "crs_header.h"
#include "local_vec_store.h"

using namespace fm;

void read_data(char *data, size_t size, size_t num, off_t off, FILE *stream)
{
	int iret = fseek(stream, off, SEEK_SET);
	assert(iret == 0);
	size_t ret = fread(data, size, num, stream);
	assert(ret == num);
}

class adj2crs_apply_operate: public arr_apply_operate
{
public:
	adj2crs_apply_operate(): arr_apply_operate(0) {
	}
	virtual void run(const local_vec_store &in,
			local_vec_store &out) const;

	virtual const scalar_type &get_input_type() const {
		return get_scalar_type<char>();
	}
	virtual const scalar_type &get_output_type() const {
		return get_scalar_type<crs_idx_t>();
	}
};

void adj2crs_apply_operate::run(const local_vec_store &in,
		local_vec_store &out) const
{
	const fg::ext_mem_undirected_vertex *v
		= (const fg::ext_mem_undirected_vertex *) in.get_raw_arr();
	size_t num_edges = v->get_num_edges();
	out.resize(num_edges);
	for (size_t i = 0; i < num_edges; i++)
		out.set<crs_idx_t>(i, v->get_neighbor(i));
}

void export_crs(vector_vector::ptr adjs, const std::string &output_file)
{
	vector_vector::ptr col_idxs = vector_vector::cast(
			adjs->apply(adj2crs_apply_operate()));
	vector::ptr col_vec = col_idxs->cat();
	std::vector<crs_idx_t> offs(adjs->get_num_vecs() + 1);
	for (size_t i = 0; i < adjs->get_num_vecs(); i++) {
		offs[i + 1] = offs[i] + col_idxs->get_length(i);
	}

	FILE *f = fopen(output_file.c_str(), "w");
	if (f == NULL) {
		fprintf(stderr, "can't open %s: %s\n", output_file.c_str(), strerror(errno));
		exit(1);
	}

	// This is an adjacency matrix of a graph, so it has the same number of
	// rows and columns.
	crs_header header(adjs->get_num_vecs(), adjs->get_num_vecs(),
			col_vec->get_length());
	size_t ret = fwrite(&header, sizeof(header), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write header: %s\n", strerror(errno));
		exit(1);
	}

	ret = fwrite(offs.data(), offs.size() * sizeof(offs[0]), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write the row pointers: %s\n", strerror(errno));
		exit(1);
	}
	ret = fwrite(dynamic_cast<const detail::mem_vec_store &>(col_vec->get_data()).get_raw_arr(),
			col_vec->get_length() * col_vec->get_entry_size(), 1, f);
	if (ret == 0) {
		fprintf(stderr, "can't write col idx: %s\n", strerror(errno));
		exit(1);
	}

	fclose(f);
}

int main(int argc, char *argv[])
{
	if (argc < 4) {
		fprintf(stderr, "el2crs graph_file index_file crs_file\n");
		return -1;
	}

	std::string graph_file = std::string(argv[1]);
	std::string index_file = std::string(argv[2]);
	std::string crs_file = std::string(argv[3]);

	fg::vertex_index::ptr vindex = fg::vertex_index::load(index_file);

	FILE *f = fopen(graph_file.c_str(), "r");
	if (f == NULL) {
		fprintf(stderr, "can't open %s: %s\n", graph_file.c_str(),
				strerror(errno));
		return -1;
	}

	size_t out_size = get_out_size(vindex);
	off_t out_off = get_out_off(vindex);
	detail::raw_data_array out_data(out_size);
	read_data(out_data.get_raw(), out_size, 1, out_off, f);
	std::vector<off_t> out_offs(vindex->get_num_vertices() + 1);
	init_out_offs(vindex, out_offs);
	for (size_t i = 0; i < out_offs.size(); i++)
		out_offs[i] -= out_off;
	vector_vector::ptr out_adjs = vector_vector::create(
			out_data, out_offs, get_scalar_type<char>());

	export_crs(out_adjs, crs_file);
	out_adjs = NULL;

	if (vindex->get_graph_header().is_directed_graph()) {
		std::string t_crs_file = std::string("t_") + crs_file;

		size_t in_size = get_in_size(vindex);
		off_t in_off = get_in_off(vindex);
		detail::raw_data_array in_data(in_size);
		read_data(in_data.get_raw(), in_size, 1, in_off, f);
		std::vector<off_t> in_offs(vindex->get_num_vertices() + 1);
		init_in_offs(vindex, in_offs);
		for (size_t i = 0; i < in_offs.size(); i++)
			in_offs[i] -= in_off;
		vector_vector::ptr in_adjs = vector_vector::create(
				in_data, in_offs, get_scalar_type<char>());

		export_crs(in_adjs, t_crs_file);
	}

	fclose(f);
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "Animation/OgreBone.h"
#include "OgreNode.h"
#include "OgreLogManager.h"

#include "Math/Array/OgreBoneMemoryManager.h"
#include "Math/Array/OgreKfTransform.h"
#include "Math/Array/OgreBooleanMask.h"

#ifndef NDEBUG
	#define CACHED_TRANSFORM_OUT_OF_DATE() this->setCachedTransformOutOfDate()
#else
	#define CACHED_TRANSFORM_OUT_OF_DATE() ((void)0)
#endif

namespace Ogre {
	//-----------------------------------------------------------------------
	Bone::Bone() :
		IdObject( 0 ),
		mReverseBind( 0 ),
		mTransform( BoneTransform() ),
#ifndef NDEBUG
		mCachedTransformOutOfDate( true ),
		mDebugParentNode( 0 ),
		mInitialized( false ),
#endif
		mDepthLevel( 0 ),
		mParent( 0 ),
		mName( "@Dummy Bone" ),
		mBoneMemoryManager( 0 ),
		mGlobalIndex( -1 ),
		mParentIndex( -1 )
	{

	}
	//-----------------------------------------------------------------------
	Bone::~Bone()
	{
		assert( !mInitialized && "Must call _deinitialize() before destructor!" );
	}
	//-----------------------------------------------------------------------
	void Bone::_initialize( IdType id, BoneMemoryManager *boneMemoryManager,
							Bone *parent, ArrayMatrixAf4x3 const * RESTRICT_ALIAS reverseBind )
	{
		assert( !mInitialized );

#ifndef NDEBUG
		mInitialized = true;
#endif

		this->_setId( id );
		mReverseBind		= reverseBind;
		mParent				= parent;
		mBoneMemoryManager	= boneMemoryManager;

		if( mParent )
			mDepthLevel = mParent->mDepthLevel + 1;

		//Will initialize mTransform
		mBoneMemoryManager->nodeCreated( mTransform, mDepthLevel );
		mTransform.mOwner[mTransform.mIndex] = this;
		if( mParent )
		{
			const BoneTransform parentTransform = mParent->mTransform;
			mTransform.mParentTransform[mTransform.mIndex] =
								&parentTransform.mDerivedTransform[parentTransform.mIndex];

			mParent->mChildren.push_back( this );
			this->mParentIndex = mParent->mChildren.size() - 1;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::_deinitialize(void)
	{
		removeAllChildren();
		if( mParent )
			mParent->removeChild( this );

		if( mBoneMemoryManager )
			mBoneMemoryManager->nodeDestroyed( mTransform, mDepthLevel );

		mReverseBind		= 0;
		mBoneMemoryManager	= 0;

#ifndef NDEBUG
		mInitialized = false;
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::unsetParent(void)
	{
		if( mParent )
		{
			mTransform.mParentTransform[mTransform.mIndex] = &SimpleMatrixAf4x3::IDENTITY;
			mParent = 0;//Needs to be set now, if nodeDetached triggers a cleanup,
						//_memoryRebased will be called on us

			//BoneMemoryManager will set mTransform.mParentTransform to a dummy
			//transform (as well as transfering the memory)
			mBoneMemoryManager->nodeDettached( mTransform, mDepthLevel );

			if( mDepthLevel != 0 )
			{
				mDepthLevel = 0;

				//Propagate the change to our children
				BoneVec::const_iterator itor = mChildren.begin();
				BoneVec::const_iterator end  = mChildren.end();

				while( itor != end )
				{
					(*itor)->parentDepthLevelChanged();
					++itor;
				}
			}
		}
	}
	//-----------------------------------------------------------------------
	void Bone::parentDepthLevelChanged(void)
	{
		mBoneMemoryManager->nodeMoved( mTransform, mDepthLevel, mParent->mDepthLevel + 1 );
		mDepthLevel = mParent->mDepthLevel + 1;

		//Keep propagating changes to our children
		BoneVec::const_iterator itor = mChildren.begin();
		BoneVec::const_iterator end  = mChildren.end();

		while( itor != end )
		{
			(*itor)->parentDepthLevelChanged();
			++itor;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::setCachedTransformOutOfDate(void) const
	{
#ifndef NDEBUG
		mCachedTransformOutOfDate = true;

		BoneVec::const_iterator itor = mChildren.begin();
		BoneVec::const_iterator end  = mChildren.end();

		while( itor != end )
		{
			(*itor)->setCachedTransformOutOfDate();
			++itor;
		}
#else
		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
					"Do not call setCachedTransformOutOfDate in Release builds.\n"
					"Use CACHED_TRANSFORM_OUT_OF_DATE macro instead!",
					"Bone::setCachedTransformOutOfDate" );
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::resetParentTransformPtr(void)
	{
		if( mParent )
		{
			const BoneTransform parentTransform = mParent->mTransform;
			mTransform.mParentTransform[mTransform.mIndex] =
									&parentTransform.mDerivedTransform[parentTransform.mIndex];
		}

		_memoryRebased();
	}
	//-----------------------------------------------------------------------
	void Bone::_memoryRebased(void)
	{
		BoneVec::iterator itor = mChildren.begin();
		BoneVec::iterator end  = mChildren.end();
		while( itor != end )
		{
			(*itor)->resetParentTransformPtr();
			++itor;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::_setNodeParent( Node *nodeParent )
	{
		if( mParent )
		{
			OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Only Root bones call this function.",
						 "Bone::_addNodeParent" );
		}

#ifndef NDEBUG
		mDebugParentNode = nodeParent;
#endif
		if( nodeParent )
		{
			//This "Hack" just works. Don't ask. And it's fast!
			//(we're responsible for ensuring the memory layout matches)
			Transform parentTransf = nodeParent->_getTransform();
			mTransform.mParentTransform[mTransform.mIndex] = reinterpret_cast<SimpleMatrixAf4x3*>(
												&parentTransf.mDerivedTransform[parentTransf.mIndex] );
		}
		else
		{
			mTransform.mParentTransform[mTransform.mIndex] = &SimpleMatrixAf4x3::IDENTITY;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::setInheritOrientation(bool inherit)
	{
		mTransform.mInheritOrientation[mTransform.mIndex] = inherit;
		CACHED_TRANSFORM_OUT_OF_DATE();
	}
	//-----------------------------------------------------------------------
	bool Bone::getInheritOrientation(void) const
	{
		return mTransform.mInheritOrientation[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	void Bone::setInheritScale(bool inherit)
	{
		mTransform.mInheritScale[mTransform.mIndex] = inherit;
		CACHED_TRANSFORM_OUT_OF_DATE();
	}
	//-----------------------------------------------------------------------
	bool Bone::getInheritScale(void) const
	{
		return mTransform.mInheritScale[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	const SimpleMatrixAf4x3& Bone::_getFullTransformUpdated(void)
	{
		_updateFromParent();
		return mTransform.mDerivedTransform[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	void Bone::_updateFromParent(void)
	{
		if( mParent )
			mParent->_updateFromParent();

		updateFromParentImpl();
	}
	//-----------------------------------------------------------------------
	void Bone::updateFromParentImpl(void)
	{
		//Retrieve from parents. Unfortunately we need to do SoA -> AoS -> SoA conversion
		ArrayMatrixAf4x3 parentMat;
		parentMat.loadFromAoS( mTransform.mParentTransform );

		//ArrayMatrixAf4x3::retain is quite lengthy in instruction count, and the
		//general case is to inherit both attributes. This branch is justified.
		if( BooleanMask4::allBitsSet( mTransform.mInheritOrientation, mTransform.mInheritScale ) )
		{
			ArrayMaskR inheritOrientation	= BooleanMask4::getMask( mTransform.mInheritOrientation );
			ArrayMaskR inheritScale			= BooleanMask4::getMask( mTransform.mInheritScale );
			parentMat.retain( inheritOrientation, inheritScale );
		}

		//BIG TODO: When in local space, reverse bind can be applied before making the transforms.
		ArrayMatrixAf4x3 mat;
		mat.makeTransform( *mTransform.mPosition, *mTransform.mScale, *mTransform.mOrientation );
		mat = ((*reverseBind) * mat) * parentMat;

		/*
			Calculating the bone matrices
			-----------------------------
			Now that we have the derived scaling factors, orientations & positions matrices,
			we have to compute the Matrix4x3 to apply to the vertices of a mesh.
			Because any modification of a vertex has to be relative to the bone, we must
			first reverse transform by the Bone's original derived position/orientation/scale,
			then transform by the new derived position/orientation/scale.
		*/
		mat.storeToAoS( mTransform.mDerivedTransform );

#ifndef NDEBUG
		for( size_t j=0; j<ARRAY_PACKED_REALS; ++j )
		{
			if( mTransform.mOwner[j] )
				mTransform.mOwner[j]->mCachedTransformOutOfDate = false;
		}
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::updateAllTransforms( const size_t numNodes, BoneTransform t,
									ArrayMatrixAf4x3 const * RESTRICT_ALIAS _reverseBind,
									size_t numBinds )
	{
		size_t currentBind = 0;
		numBinds = (numBinds + ARRAY_PACKED_REALS - 1) / ARRAY_PACKED_REALS;

		ArrayMatrixAf4x3 derivedTransform;
		for( size_t i=0; i<numNodes; i += ARRAY_PACKED_REALS )
		{
			//Retrieve from parents. Unfortunately we need to do SoA -> AoS -> SoA conversion
			ArrayMatrixAf4x3 parentMat;

			parentMat.loadFromAoS( t.mParentTransform );

			//ArrayMatrixAf4x3::retain is quite lengthy in instruction count, and the
			//general case is to inherit both attributes. This branch is justified.
			if( !BooleanMask4::allBitsSet( t.mInheritOrientation, t.mInheritScale ) )
			{
				ArrayMaskR inheritOrientation	= BooleanMask4::getMask( t.mInheritOrientation );
				ArrayMaskR inheritScale			= BooleanMask4::getMask( t.mInheritScale );
				parentMat.retain( inheritOrientation, inheritScale );
			}

			const ArrayMatrixAf4x3 * RESTRICT_ALIAS reverseBind = _reverseBind + currentBind;

			derivedTransform.makeTransform( *t.mPosition, *t.mScale, *t.mOrientation );
			derivedTransform = ((*reverseBind) * derivedTransform) * parentMat;

			/*
				Calculating the bone matrices
				-----------------------------
				Now that we have the derived scaling factors, orientations & positions matrices,
				we have to compute the Matrix4x3 to apply to the vertices of a mesh.
				Because any modification of a vertex has to be relative to the bone, we must
				first reverse transform by the Bone's original derived position/orientation/scale,
				then transform by the new derived position/orientation/scale.
			*/
			derivedTransform.storeToAoS( t.mDerivedTransform );

#ifndef NDEBUG
			for( size_t j=0; j<ARRAY_PACKED_REALS; ++j )
			{
				if( t.mOwner[j] )
					t.mOwner[j]->mCachedTransformOutOfDate = false;
			}
#endif

			t.advancePack();
			currentBind = ( currentBind + 1 ) % numBinds;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::removeChild( Bone* child )
	{
		assert( child->getParent() == this && "Node says it's not our child" );
		assert( child->mParentIndex < mChildren.size() && "mParentIndex was out of date!!!" );

		if( child->mParentIndex < mChildren.size() )
		{
			BoneVec::iterator itor = mChildren.begin() + child->mParentIndex;

			assert( child == *itor && "mParentIndex was out of date!!!" );

			if( child == *itor )
			{
				itor = efficientVectorRemove( mChildren, itor );
				child->unsetParent();
				child->mParentIndex = -1;

				//The node that was at the end got swapped and has now a different index
				if( itor != mChildren.end() )
					(*itor)->mParentIndex = itor - mChildren.begin();
			}
		}
	}
	//-----------------------------------------------------------------------
	void Bone::removeAllChildren(void)
	{
		BoneVec::iterator itor = mChildren.begin();
		BoneVec::iterator end  = mChildren.end();
		while( itor != end )
		{
			(*itor)->unsetParent();
			(*itor)->mParentIndex = -1;
			++itor;
		}
		mChildren.clear();
	}
}

#undef CACHED_TRANSFORM_OUT_OF_DATE
<commit_msg>Fixed silly compile error<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "Animation/OgreBone.h"
#include "OgreNode.h"
#include "OgreLogManager.h"

#include "Math/Array/OgreBoneMemoryManager.h"
#include "Math/Array/OgreKfTransform.h"
#include "Math/Array/OgreBooleanMask.h"

#ifndef NDEBUG
	#define CACHED_TRANSFORM_OUT_OF_DATE() this->setCachedTransformOutOfDate()
#else
	#define CACHED_TRANSFORM_OUT_OF_DATE() ((void)0)
#endif

namespace Ogre {
	//-----------------------------------------------------------------------
	Bone::Bone() :
		IdObject( 0 ),
		mReverseBind( 0 ),
		mTransform( BoneTransform() ),
#ifndef NDEBUG
		mCachedTransformOutOfDate( true ),
		mDebugParentNode( 0 ),
		mInitialized( false ),
#endif
		mDepthLevel( 0 ),
		mParent( 0 ),
		mName( "@Dummy Bone" ),
		mBoneMemoryManager( 0 ),
		mGlobalIndex( -1 ),
		mParentIndex( -1 )
	{

	}
	//-----------------------------------------------------------------------
	Bone::~Bone()
	{
		assert( !mInitialized && "Must call _deinitialize() before destructor!" );
	}
	//-----------------------------------------------------------------------
	void Bone::_initialize( IdType id, BoneMemoryManager *boneMemoryManager,
							Bone *parent, ArrayMatrixAf4x3 const * RESTRICT_ALIAS reverseBind )
	{
		assert( !mInitialized );

#ifndef NDEBUG
		mInitialized = true;
#endif

		this->_setId( id );
		mReverseBind		= reverseBind;
		mParent				= parent;
		mBoneMemoryManager	= boneMemoryManager;

		if( mParent )
			mDepthLevel = mParent->mDepthLevel + 1;

		//Will initialize mTransform
		mBoneMemoryManager->nodeCreated( mTransform, mDepthLevel );
		mTransform.mOwner[mTransform.mIndex] = this;
		if( mParent )
		{
			const BoneTransform parentTransform = mParent->mTransform;
			mTransform.mParentTransform[mTransform.mIndex] =
								&parentTransform.mDerivedTransform[parentTransform.mIndex];

			mParent->mChildren.push_back( this );
			this->mParentIndex = mParent->mChildren.size() - 1;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::_deinitialize(void)
	{
		removeAllChildren();
		if( mParent )
			mParent->removeChild( this );

		if( mBoneMemoryManager )
			mBoneMemoryManager->nodeDestroyed( mTransform, mDepthLevel );

		mReverseBind		= 0;
		mBoneMemoryManager	= 0;

#ifndef NDEBUG
		mInitialized = false;
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::unsetParent(void)
	{
		if( mParent )
		{
			mTransform.mParentTransform[mTransform.mIndex] = &SimpleMatrixAf4x3::IDENTITY;
			mParent = 0;//Needs to be set now, if nodeDetached triggers a cleanup,
						//_memoryRebased will be called on us

			//BoneMemoryManager will set mTransform.mParentTransform to a dummy
			//transform (as well as transfering the memory)
			mBoneMemoryManager->nodeDettached( mTransform, mDepthLevel );

			if( mDepthLevel != 0 )
			{
				mDepthLevel = 0;

				//Propagate the change to our children
				BoneVec::const_iterator itor = mChildren.begin();
				BoneVec::const_iterator end  = mChildren.end();

				while( itor != end )
				{
					(*itor)->parentDepthLevelChanged();
					++itor;
				}
			}
		}
	}
	//-----------------------------------------------------------------------
	void Bone::parentDepthLevelChanged(void)
	{
		mBoneMemoryManager->nodeMoved( mTransform, mDepthLevel, mParent->mDepthLevel + 1 );
		mDepthLevel = mParent->mDepthLevel + 1;

		//Keep propagating changes to our children
		BoneVec::const_iterator itor = mChildren.begin();
		BoneVec::const_iterator end  = mChildren.end();

		while( itor != end )
		{
			(*itor)->parentDepthLevelChanged();
			++itor;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::setCachedTransformOutOfDate(void) const
	{
#ifndef NDEBUG
		mCachedTransformOutOfDate = true;

		BoneVec::const_iterator itor = mChildren.begin();
		BoneVec::const_iterator end  = mChildren.end();

		while( itor != end )
		{
			(*itor)->setCachedTransformOutOfDate();
			++itor;
		}
#else
		OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR,
					"Do not call setCachedTransformOutOfDate in Release builds.\n"
					"Use CACHED_TRANSFORM_OUT_OF_DATE macro instead!",
					"Bone::setCachedTransformOutOfDate" );
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::resetParentTransformPtr(void)
	{
		if( mParent )
		{
			const BoneTransform parentTransform = mParent->mTransform;
			mTransform.mParentTransform[mTransform.mIndex] =
									&parentTransform.mDerivedTransform[parentTransform.mIndex];
		}

		_memoryRebased();
	}
	//-----------------------------------------------------------------------
	void Bone::_memoryRebased(void)
	{
		BoneVec::iterator itor = mChildren.begin();
		BoneVec::iterator end  = mChildren.end();
		while( itor != end )
		{
			(*itor)->resetParentTransformPtr();
			++itor;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::_setNodeParent( Node *nodeParent )
	{
		if( mParent )
		{
			OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Only Root bones call this function.",
						 "Bone::_addNodeParent" );
		}

#ifndef NDEBUG
		mDebugParentNode = nodeParent;
#endif
		if( nodeParent )
		{
			//This "Hack" just works. Don't ask. And it's fast!
			//(we're responsible for ensuring the memory layout matches)
			Transform parentTransf = nodeParent->_getTransform();
			mTransform.mParentTransform[mTransform.mIndex] = reinterpret_cast<SimpleMatrixAf4x3*>(
												&parentTransf.mDerivedTransform[parentTransf.mIndex] );
		}
		else
		{
			mTransform.mParentTransform[mTransform.mIndex] = &SimpleMatrixAf4x3::IDENTITY;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::setInheritOrientation(bool inherit)
	{
		mTransform.mInheritOrientation[mTransform.mIndex] = inherit;
		CACHED_TRANSFORM_OUT_OF_DATE();
	}
	//-----------------------------------------------------------------------
	bool Bone::getInheritOrientation(void) const
	{
		return mTransform.mInheritOrientation[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	void Bone::setInheritScale(bool inherit)
	{
		mTransform.mInheritScale[mTransform.mIndex] = inherit;
		CACHED_TRANSFORM_OUT_OF_DATE();
	}
	//-----------------------------------------------------------------------
	bool Bone::getInheritScale(void) const
	{
		return mTransform.mInheritScale[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	const SimpleMatrixAf4x3& Bone::_getFullTransformUpdated(void)
	{
		_updateFromParent();
		return mTransform.mDerivedTransform[mTransform.mIndex];
	}
	//-----------------------------------------------------------------------
	void Bone::_updateFromParent(void)
	{
		if( mParent )
			mParent->_updateFromParent();

		updateFromParentImpl();
	}
	//-----------------------------------------------------------------------
	void Bone::updateFromParentImpl(void)
	{
		//Retrieve from parents. Unfortunately we need to do SoA -> AoS -> SoA conversion
		ArrayMatrixAf4x3 parentMat;
		parentMat.loadFromAoS( mTransform.mParentTransform );

		//ArrayMatrixAf4x3::retain is quite lengthy in instruction count, and the
		//general case is to inherit both attributes. This branch is justified.
		if( BooleanMask4::allBitsSet( mTransform.mInheritOrientation, mTransform.mInheritScale ) )
		{
			ArrayMaskR inheritOrientation	= BooleanMask4::getMask( mTransform.mInheritOrientation );
			ArrayMaskR inheritScale			= BooleanMask4::getMask( mTransform.mInheritScale );
			parentMat.retain( inheritOrientation, inheritScale );
		}

		//BIG TODO: When in local space, reverse bind can be applied before making the transforms.
		ArrayMatrixAf4x3 mat;
		mat.makeTransform( *mTransform.mPosition, *mTransform.mScale, *mTransform.mOrientation );
		mat = ((*mReverseBind) * mat) * parentMat;

		/*
			Calculating the bone matrices
			-----------------------------
			Now that we have the derived scaling factors, orientations & positions matrices,
			we have to compute the Matrix4x3 to apply to the vertices of a mesh.
			Because any modification of a vertex has to be relative to the bone, we must
			first reverse transform by the Bone's original derived position/orientation/scale,
			then transform by the new derived position/orientation/scale.
		*/
		mat.storeToAoS( mTransform.mDerivedTransform );

#ifndef NDEBUG
		for( size_t j=0; j<ARRAY_PACKED_REALS; ++j )
		{
			if( mTransform.mOwner[j] )
				mTransform.mOwner[j]->mCachedTransformOutOfDate = false;
		}
#endif
	}
	//-----------------------------------------------------------------------
	void Bone::updateAllTransforms( const size_t numNodes, BoneTransform t,
									ArrayMatrixAf4x3 const * RESTRICT_ALIAS _reverseBind,
									size_t numBinds )
	{
		size_t currentBind = 0;
		numBinds = (numBinds + ARRAY_PACKED_REALS - 1) / ARRAY_PACKED_REALS;

		ArrayMatrixAf4x3 derivedTransform;
		for( size_t i=0; i<numNodes; i += ARRAY_PACKED_REALS )
		{
			//Retrieve from parents. Unfortunately we need to do SoA -> AoS -> SoA conversion
			ArrayMatrixAf4x3 parentMat;

			parentMat.loadFromAoS( t.mParentTransform );

			//ArrayMatrixAf4x3::retain is quite lengthy in instruction count, and the
			//general case is to inherit both attributes. This branch is justified.
			if( !BooleanMask4::allBitsSet( t.mInheritOrientation, t.mInheritScale ) )
			{
				ArrayMaskR inheritOrientation	= BooleanMask4::getMask( t.mInheritOrientation );
				ArrayMaskR inheritScale			= BooleanMask4::getMask( t.mInheritScale );
				parentMat.retain( inheritOrientation, inheritScale );
			}

			const ArrayMatrixAf4x3 * RESTRICT_ALIAS reverseBind = _reverseBind + currentBind;

			derivedTransform.makeTransform( *t.mPosition, *t.mScale, *t.mOrientation );
			derivedTransform = ((*reverseBind) * derivedTransform) * parentMat;

			/*
				Calculating the bone matrices
				-----------------------------
				Now that we have the derived scaling factors, orientations & positions matrices,
				we have to compute the Matrix4x3 to apply to the vertices of a mesh.
				Because any modification of a vertex has to be relative to the bone, we must
				first reverse transform by the Bone's original derived position/orientation/scale,
				then transform by the new derived position/orientation/scale.
			*/
			derivedTransform.storeToAoS( t.mDerivedTransform );

#ifndef NDEBUG
			for( size_t j=0; j<ARRAY_PACKED_REALS; ++j )
			{
				if( t.mOwner[j] )
					t.mOwner[j]->mCachedTransformOutOfDate = false;
			}
#endif

			t.advancePack();
			currentBind = ( currentBind + 1 ) % numBinds;
		}
	}
	//-----------------------------------------------------------------------
	void Bone::removeChild( Bone* child )
	{
		assert( child->getParent() == this && "Node says it's not our child" );
		assert( child->mParentIndex < mChildren.size() && "mParentIndex was out of date!!!" );

		if( child->mParentIndex < mChildren.size() )
		{
			BoneVec::iterator itor = mChildren.begin() + child->mParentIndex;

			assert( child == *itor && "mParentIndex was out of date!!!" );

			if( child == *itor )
			{
				itor = efficientVectorRemove( mChildren, itor );
				child->unsetParent();
				child->mParentIndex = -1;

				//The node that was at the end got swapped and has now a different index
				if( itor != mChildren.end() )
					(*itor)->mParentIndex = itor - mChildren.begin();
			}
		}
	}
	//-----------------------------------------------------------------------
	void Bone::removeAllChildren(void)
	{
		BoneVec::iterator itor = mChildren.begin();
		BoneVec::iterator end  = mChildren.end();
		while( itor != end )
		{
			(*itor)->unsetParent();
			(*itor)->mParentIndex = -1;
			++itor;
		}
		mChildren.clear();
	}
}

#undef CACHED_TRANSFORM_OUT_OF_DATE
<|endoftext|>


<commit_before>#include "Camera.h"
#include <GL\freeglut.h>
#include <iostream>

float Camera::fov = 45.0f;
float Camera::aspect = 1.0f;

float hAngle = 3.14f;
float vAngle = 0.0f;
float speed = 3.0f;
float mouseSpeed = 0.05f;

glm::vec3 position = glm::vec3(4, 3, 3);
glm::vec3 direction, right, up;

float deltaTime = 0.0f;
double cursor_x, cursor_y;
bool hRotationEnabled, vRotationEnabled;

glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;

glm::mat4 Camera::GetProjectionMatrix() {
	return ProjectionMatrix;
}

glm::mat4 Camera::GetViewMatrix()
{
	return ViewMatrix;
}

void updateMouseLocation(int x, int y)
{
	std::cout << "x=" << x << "y=" << y << std::endl;
	if (hRotationEnabled)
		hAngle += mouseSpeed * deltaTime * float(1024 / 2 - cursor_x);
	if (vRotationEnabled)
		vAngle += mouseSpeed * deltaTime * float(768 / 2 - cursor_y);
}

/*
 * Callback for glutMouseFunc()
 * https://www.opengl.org/documentation/specs/glut/spec3/node50.html
*/
void onMouseButton(int button, int state, int x, int y)
{
	std::cout << "button: " << button << "\tstate: " << state << std::endl;
	hRotationEnabled = false;
	vRotationEnabled = false;
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		hRotationEnabled = true;
		vRotationEnabled = true;
	}
}

void onKeyPressed(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)
		position += direction * speed;
	if (key == GLUT_KEY_DOWN)
		position -= direction * speed;
	if (key == GLUT_KEY_RIGHT)
		position += right * speed;
	if (key == GLUT_KEY_LEFT)
		position -= right * speed;
}

//TODO switch from hardcoding in 1024/768, aspect, etc
void Camera::ComputeMatrices()
{
	static int pTime = glutGet(GLUT_ELAPSED_TIME); // called once. Wrong! TODO: Fix
	int cTime = glutGet(GLUT_ELAPSED_TIME);
	deltaTime = float(cTime - pTime)/1000.0f; // time elapsed in seconds

	// listen for mouse input
	//TODO call outside of this class
	glutMotionFunc(updateMouseLocation);

	direction = glm::vec3(
		cos(vAngle) * sin(hAngle),
		sin(vAngle),
		cos(vAngle) * cos(hAngle));

	right = glm::vec3(
		sin(hAngle - 3.14f/2.0f),
		0,
		cos(hAngle - 3.14/2.0f));

	up = glm::cross(right, direction);

	// listen for mouse events
	//TODO call outside of this class
	glutSpecialFunc(onKeyPressed);
	glutMouseFunc(onMouseButton);

	ProjectionMatrix = glm::perspective(glm::radians(fov), 4.0f / 3.0f, 0.1f, 100.0f);
	ViewMatrix = glm::lookAt(
			position, // camera position
			direction, // camera looks here
			up
		);
	pTime = cTime; // update "previous" time

}

<commit_msg>Fix mouse movement<commit_after>#include "Camera.h"
#include <GL\freeglut.h>
#include <iostream>

float Camera::fov = 45.0f;
float Camera::aspect = 1.0f;

float hAngle = 3.14f;
float vAngle = 0.0f;
float speed = 3.0f;
float mouseSpeed = 0.5f;

glm::vec3 position = glm::vec3(0, 0, 5);
glm::vec3 direction, right, up;

float deltaTime = 0.0f;
double x_origin, y_origin;
bool hRotationEnabled, vRotationEnabled;

glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;

glm::mat4 Camera::GetProjectionMatrix() {
	return ProjectionMatrix;
}

glm::mat4 Camera::GetViewMatrix()
{
	return ViewMatrix;
}

void updateMouseLocation(int x, int y)
{
	double dx = x - x_origin;
	double dy = y - y_origin;
	std::cout << "deltaTime" << deltaTime <<  std::endl;
	if (hRotationEnabled)
		hAngle += mouseSpeed * deltaTime * float(dx);
	if (vRotationEnabled)
		vAngle += mouseSpeed * deltaTime * float(dy);

	x_origin = x;
	y_origin = y;
}

/*
 * Callback for glutMouseFunc()
 * https://www.opengl.org/documentation/specs/glut/spec3/node50.html
*/
void onMouseButton(int button, int state, int x, int y)
{
	hRotationEnabled = false;
	vRotationEnabled = false;
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		x_origin = x;
		y_origin = y;
		hRotationEnabled = true;
		vRotationEnabled = true;
	}
	else if (button == 3 && state == GLUT_DOWN) // Mouse wheel down
	{
		position += direction * speed;
	}
	else if (button == 4 && state == GLUT_DOWN) // Mouse wheel up
	{
		position -= direction * speed;
	}
}

void onKeyPressed(int key, int x, int y)
{

	std::cout << "deltaTime" << deltaTime << std::endl;
	if (key == GLUT_KEY_UP)
		position += direction * speed;
	if (key == GLUT_KEY_DOWN)
		position -= direction * speed;
	if (key == GLUT_KEY_RIGHT)
		position += right * speed;
	if (key == GLUT_KEY_LEFT)
		position -= right * speed;
}

//TODO switch from hardcoding in 1024/768, aspect, etc
void Camera::ComputeMatrices()
{
	static int pTime = glutGet(GLUT_ELAPSED_TIME); // called once. Wrong! TODO: Fix
	int cTime = glutGet(GLUT_ELAPSED_TIME);
	deltaTime = float(cTime - pTime)/1000.0f; // time elapsed in seconds

	// listen for mouse input
	//TODO call outside of this class
	glutMotionFunc(updateMouseLocation);

	direction = glm::vec3(
		cos(vAngle) * sin(hAngle),
		sin(vAngle),
		cos(vAngle) * cos(hAngle));

	right = glm::vec3(
		sin(hAngle - 3.14f/2.0f),
		0,
		cos(hAngle - 3.14/2.0f));

	up = cross(right, direction);

	// listen for mouse events
	//TODO call outside of this class
	glutSpecialFunc(onKeyPressed);
	glutMouseFunc(onMouseButton);

	ProjectionMatrix = glm::perspective(glm::radians(fov), 4.0f / 3.0f, 0.1f, 100.0f);
	ViewMatrix = lookAt(
			position, // camera position
			position + direction, // camera looks here
			up
		);
	pTime = cTime; // update "previous" time

}

<|endoftext|>


<commit_before>//
// sim_tools.cpp
//
// Program to read and process contents of a SIM file
//
// $Id: sim.cpp 1354 2010-11-11 16:20:09Z js10 $
//
//
// Author: Jennifer Liddle <js10@sanger.ac.uk, jennifer@jsquared.co.uk>, Iain Bancarz <ib5@sanger.ac.uk>
//
// Copyright (c) 2009 - 2013 Genome Research Ltd. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Genome Research Ltd nor the names of the
// contributors may be used to endorse or promote products derived from
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL GENOME RESEARCH LTD. BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

// TODO Keep command line parsing in this file; move analysis logic into a separate class. Tidies up code and enables testing.

#include <getopt.h>

#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <iomanip>
#include <algorithm>

#include "commands.h"
#include "Sim.h"
#include "Gtc.h"
#include "QC.h"
#include "Manifest.h"
#include "json/json.h"

using namespace std;

static struct option long_options[] = {
                   {"infile", 1, 0, 0},
                   {"outfile", 1, 0, 0},
                   {"man_file", 1, 0, 0},
                   {"man_dir", 1, 0, 0},
                   {"normalize", 0, 0, 0},
                   {"verbose", 0, 0, 0},
                   {"start", 1, 0, 0},
                   {"end", 1, 0, 0},
                   {"magnitude", 1, 0, 0},
                   {"xydiff", 1, 0, 0},
                   {0, 0, 0, 0}
               };

void showUsage(int argc, char *argv[])
{
	string command = "";

	if (argc > 2) command = argv[2];

	cout << endl;
	if (command == "create") {
		cout << "Usage:   " << argv[0] << " create [options]" << endl << endl;
		cout << "Create a SIM file from a list of GTC files" << endl<< endl;
		cout << "Options: --infile <filename>    File containing list of GTC files to process" << endl;
		cout << "         --outfile <filename>   Name of SIM file to create or '-' for STDOUT" << endl;
		cout << "         --man_file <dirname>    Directory to look for Manifest file in" << endl;
		cout << "         --normalize            Normalize the intensities (default is raw values)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "illuminus") {
		cout << "Usage:   " << argv[0] << " illuminus [options]" << endl << endl;
		cout << "Create an Illuminus file from a SIM file" << endl<< endl;
		cout << "Options: --infile <filename>    Name of SIM file to process or '-' for STDIN" << endl;
		cout << "         --outfile <filename>   Name of Illuminus file to create or '-' for STDOUT" << endl;
		cout << "         --man_file <dirname>    Directory to look for Manifest file in" << endl;
		cout << "         --start <index>        Which SNP to start processing at (default is to start at the beginning)" << endl;
		cout << "         --end <index>          Which SNP to end processing at (default is to continue until the end)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "genosnp") {
		cout << "Usage:   " << argv[0] << " genosnp [options]" << endl << endl;
		cout << "Create a GenoSNP file from a SIM file" << endl<< endl;
		cout << "Options: --infile   The name of the SIM file or '-' for STDIN" << endl;
		cout << "         --outfile  Name of GenoSNP file to create or '-' for STDOUT" << endl;
		cout << "         --start <index>        Which sample to start processing at (default is to start at the beginning)" << endl;
		cout << "         --end <index>          Which sample to end processing at (default is to continue until the end)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "view") {
		cout << "Usage:   " << argv[0] << " view [options]" << endl << endl;
		cout << "Display some information from a SIM file" << endl<< endl;
		cout << "Options: --infile   The name of the SIM file or '-' for STDIN" << endl;
		cout << "         --verbose  Display intensities as well as header information" << endl;
		exit(0);
	}

	if (command == "qc") {
		cout << "Usage:   " << argv[0] << " qc [options]" << endl << endl;
		cout << "Compute genotyping QC metrics and write to text files" << endl<< endl;
		cout << "Options: --infile      The name of the SIM file (cannot accept STDIN)" << endl;
		cout << "         --magnitude   Output file for sample magnitude (normalised by SNP); cannot use STDOUT" << endl;
		cout << "         --xydiff      Output file for XY intensity difference; cannot use STDOUT" << endl;
		cout << "         --verbose     Show progress messages to STDERR" << endl;
		exit(0);
	}

	cout << "Usage:   " << argv[0] << " <command> [options]" << endl;
	cout << "Command: view        Dump SIM file to screen" << endl;
	cout << "         create      Create a SIM file from GTC files" << endl;
	cout << "         illuminus   Produce Illuminus output" << endl;
	cout << "         genosnp     Produce GenoSNP output" << endl;
	cout << "         qc          Produce QC metrics" << endl;
	cout << "         help        Display this help. Use 'help <command>' for more help" << endl;
	exit(0);
}

int main(int argc, char *argv[])
{
	string infile = "-";
	string outfile = "-";
	string manfile = "";
	string magnitude = "";
	string xydiff = "";
	bool verbose = false;
	bool normalize = false;
	int start_pos = 0;
	int end_pos = -1;
	int option_index = -1;
	int c;

	// placeholder -- create Commander object
	Commander *commander = new Commander();

	// Get command
	if (argc < 2) showUsage(argc,argv);
	string command = argv[1];
	if (command == "help") showUsage(argc, argv);

	// get options
	while ( (c=getopt_long(argc,argv,"h?",long_options,&option_index)) != -1) {
		if (c == '?') showUsage(argc,argv);	// unknown option
		if (option_index > -1) {
			string option = long_options[option_index].name;
			if (option == "infile") infile = optarg;
			if (option == "outfile") outfile = optarg;
			if (option == "verbose") verbose = true;
			if (option == "man_file") manfile = optarg;
			if (option == "man_dir") manfile = optarg;
			if (option == "normalize") normalize = true;
			if (option == "start") start_pos = atoi(optarg);
			if (option == "end") end_pos = atoi(optarg);
			if (option == "magnitude") magnitude = optarg;
			if (option == "xydiff") xydiff = optarg;
		}
	}

	// Allow stdin and stdout as synonyms for "-"
	if (infile == "stdin") infile = "-";
	if (outfile == "stdout") outfile = "-";

	// Process the command
	try {
	  if (command == "view") {
	    commander->commandView(infile, verbose);
	  } else if (command == "create") {
	    commander->commandCreate(infile, outfile, normalize,
				     manfile, verbose);
	  } else if (command == "illuminus") {
	    commander->commandIlluminus(infile, outfile, manfile,
					start_pos, end_pos, verbose);
	  } else if (command == "genosnp") {
	    commander->commandGenoSNP(infile, outfile, manfile,
				      start_pos, end_pos, verbose);
	  } else if (command == "qc") {
	    commander->commandQC(infile, magnitude, xydiff, verbose);
	  } else {
	    cerr << "Unknown command '" << command << "'" << endl;
	    showUsage(argc,argv);
	  }
	} catch (const char *error_msg) {
		cerr << error_msg << endl << endl;
		exit(1);
	}
	catch (string error_msg) {
		cerr << error_msg << endl << endl;
		exit(1);
	}
	delete commander;
	return 0;
}

<commit_msg>Remove unnecessary import statements, move Commander initialization<commit_after>//
// sim_tools.cpp
//
// Program to read and process contents of a SIM file
//
// $Id: sim.cpp 1354 2010-11-11 16:20:09Z js10 $
//
//
// Author: Jennifer Liddle <js10@sanger.ac.uk, jennifer@jsquared.co.uk>, Iain Bancarz <ib5@sanger.ac.uk>
//
// Copyright (c) 2009 - 2013 Genome Research Ltd. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Genome Research Ltd nor the names of the
// contributors may be used to endorse or promote products derived from
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL GENOME RESEARCH LTD. BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

// TODO Keep command line parsing in this file; move analysis logic into a separate class. Tidies up code and enables testing.

#include <getopt.h>
#include <iostream>
#include "commands.h"

using namespace std;

static struct option long_options[] = {
                   {"infile", 1, 0, 0},
                   {"outfile", 1, 0, 0},
                   {"man_file", 1, 0, 0},
                   {"man_dir", 1, 0, 0},
                   {"normalize", 0, 0, 0},
                   {"verbose", 0, 0, 0},
                   {"start", 1, 0, 0},
                   {"end", 1, 0, 0},
                   {"magnitude", 1, 0, 0},
                   {"xydiff", 1, 0, 0},
                   {0, 0, 0, 0}
               };

void showUsage(int argc, char *argv[])
{
	string command = "";

	if (argc > 2) command = argv[2];

	cout << endl;
	if (command == "create") {
		cout << "Usage:   " << argv[0] << " create [options]" << endl << endl;
		cout << "Create a SIM file from a list of GTC files" << endl<< endl;
		cout << "Options: --infile <filename>    File containing list of GTC files to process" << endl;
		cout << "         --outfile <filename>   Name of SIM file to create or '-' for STDOUT" << endl;
		cout << "         --man_file <dirname>    Directory to look for Manifest file in" << endl;
		cout << "         --normalize            Normalize the intensities (default is raw values)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "illuminus") {
		cout << "Usage:   " << argv[0] << " illuminus [options]" << endl << endl;
		cout << "Create an Illuminus file from a SIM file" << endl<< endl;
		cout << "Options: --infile <filename>    Name of SIM file to process or '-' for STDIN" << endl;
		cout << "         --outfile <filename>   Name of Illuminus file to create or '-' for STDOUT" << endl;
		cout << "         --man_file <dirname>    Directory to look for Manifest file in" << endl;
		cout << "         --start <index>        Which SNP to start processing at (default is to start at the beginning)" << endl;
		cout << "         --end <index>          Which SNP to end processing at (default is to continue until the end)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "genosnp") {
		cout << "Usage:   " << argv[0] << " genosnp [options]" << endl << endl;
		cout << "Create a GenoSNP file from a SIM file" << endl<< endl;
		cout << "Options: --infile   The name of the SIM file or '-' for STDIN" << endl;
		cout << "         --outfile  Name of GenoSNP file to create or '-' for STDOUT" << endl;
		cout << "         --start <index>        Which sample to start processing at (default is to start at the beginning)" << endl;
		cout << "         --end <index>          Which sample to end processing at (default is to continue until the end)" << endl;
		cout << "         --verbose              Show progress messages to STDERR" << endl;
		exit(0);
	}

	if (command == "view") {
		cout << "Usage:   " << argv[0] << " view [options]" << endl << endl;
		cout << "Display some information from a SIM file" << endl<< endl;
		cout << "Options: --infile   The name of the SIM file or '-' for STDIN" << endl;
		cout << "         --verbose  Display intensities as well as header information" << endl;
		exit(0);
	}

	if (command == "qc") {
		cout << "Usage:   " << argv[0] << " qc [options]" << endl << endl;
		cout << "Compute genotyping QC metrics and write to text files" << endl<< endl;
		cout << "Options: --infile      The name of the SIM file (cannot accept STDIN)" << endl;
		cout << "         --magnitude   Output file for sample magnitude (normalised by SNP); cannot use STDOUT" << endl;
		cout << "         --xydiff      Output file for XY intensity difference; cannot use STDOUT" << endl;
		cout << "         --verbose     Show progress messages to STDERR" << endl;
		exit(0);
	}

	cout << "Usage:   " << argv[0] << " <command> [options]" << endl;
	cout << "Command: view        Dump SIM file to screen" << endl;
	cout << "         create      Create a SIM file from GTC files" << endl;
	cout << "         illuminus   Produce Illuminus output" << endl;
	cout << "         genosnp     Produce GenoSNP output" << endl;
	cout << "         qc          Produce QC metrics" << endl;
	cout << "         help        Display this help. Use 'help <command>' for more help" << endl;
	exit(0);
}

int main(int argc, char *argv[])
{
	string infile = "-";
	string outfile = "-";
	string manfile = "";
	string magnitude = "";
	string xydiff = "";
	bool verbose = false;
	bool normalize = false;
	int start_pos = 0;
	int end_pos = -1;
	int option_index = -1;
	int c;

	// Get command
	if (argc < 2) showUsage(argc,argv);
	string command = argv[1];
	if (command == "help") showUsage(argc, argv);

	// get options
	while ( (c=getopt_long(argc,argv,"h?",long_options,&option_index)) != -1) {
		if (c == '?') showUsage(argc,argv);	// unknown option
		if (option_index > -1) {
			string option = long_options[option_index].name;
			if (option == "infile") infile = optarg;
			if (option == "outfile") outfile = optarg;
			if (option == "verbose") verbose = true;
			if (option == "man_file") manfile = optarg;
			if (option == "man_dir") manfile = optarg;
			if (option == "normalize") normalize = true;
			if (option == "start") start_pos = atoi(optarg);
			if (option == "end") end_pos = atoi(optarg);
			if (option == "magnitude") magnitude = optarg;
			if (option == "xydiff") xydiff = optarg;
		}
	}

	// Allow stdin and stdout as synonyms for "-"
	if (infile == "stdin") infile = "-";
	if (outfile == "stdout") outfile = "-";

	Commander *commander = new Commander();
	// Process the command
	try {
	  if (command == "view") {
	    commander->commandView(infile, verbose);
	  } else if (command == "create") {
	    commander->commandCreate(infile, outfile, normalize,
				     manfile, verbose);
	  } else if (command == "illuminus") {
	    commander->commandIlluminus(infile, outfile, manfile,
					start_pos, end_pos, verbose);
	  } else if (command == "genosnp") {
	    commander->commandGenoSNP(infile, outfile, manfile,
				      start_pos, end_pos, verbose);
	  } else if (command == "qc") {
	    commander->commandQC(infile, magnitude, xydiff, verbose);
	  } else {
	    cerr << "Unknown command '" << command << "'" << endl;
	    showUsage(argc,argv);
	  }
	} catch (const char *error_msg) {
		cerr << error_msg << endl << endl;
		exit(1);
	}
	catch (string error_msg) {
		cerr << error_msg << endl << endl;
		exit(1);
	}
	delete commander;
	return 0;
}

<|endoftext|>


<commit_before>//=============================================================================
// ■ VMtest.cxx
//-----------------------------------------------------------------------------
//   虚拟机测试程序。
//   扩展名用了.cxx，意思是“×不要自动编译”。
//=============================================================================

#include "ASM76.hpp"

using namespace ASM76;

Instruct mem_test_i[] = {
	{LCMM,0x4000000,0},
	{DATI,0xABCD1234,1},
	{DATB,'V',5},
	{DATB,'M',6},
	{DATB,'7',7},
	{DATB,'6',8},
	{SLLA,0x2000000,1},
	{SLIA,0x2500000,2},
	{SLBA,0x2700000,3},
	{LDLA,0x2500000,51},
	{LDIA,0x2500000,51},
	{LDBA,0x2500000,61},
	{HALT, 0, 0},
};
Program mem_test_p {
	.size = sizeof(mem_test_i),
	.instruct = mem_test_i
};

Instruct basic_algebra_test_prgm[] = {
	{LCMM,0x100,0},
	{DATI,0x1,1},
	// $1 = $1 + $1
	// 1, 2, 4, 8, 16, ...
	{ADDL,1,1},
	{ADDL,1,1},
	{ADDL,1,1},
	{ADDL,1,1},
	// Put the result else where
	{MVRL,1,31},
	// Then divide 4
	{DATI,0x4,11},
	{DIVL,1,11},
	{HALT, 0, 0},
};

Instruct flow_control_test_prgm[] = {
	{DATB,0x1,20},
	{DATB,0xA,10},
	{DATB,0x2,15},
	{ADDL,15,15},
	{ADDL,3,20},
	{CMPI,3,10},
	{PUSH,15,1},
	{JILA, 3 * sizeof(Instruct),0},
	{HALT, 0, 0},
};

const char* const asm_test =
	"# Comments.\n"
	"DATB	0x1 $20\n"
	"DATB	0xA $10\n"
	"DATB	0x2 $15\n"
	"[loop_start]\n"
	"ADDL	$15 $15\n"
	"ADDL	$3 $20\n"
	"CMPI	$3 $10\n"
	"PUSH	$15 1\n"
	"JILA	[loop_start]\n"
	"HALT\n"
	"DD		0x7676 0xEFEF 0xABAB 0xCDCD 0x0000\n"
	"# EOF\n";

const char* const bios_test =
	"DATI	0x76 $0\n"
	"SLIA	0x100 $0\n"
	"INTX	0x1 0x100\n"
	"DATI	0xAB $0\n"
	"SLIA	0x100 $0\n"
	"INTX	0x1 0x100\n"
	"HALT\n"
	"# EOF\n";

static uint32_t test_bios_call(uint8_t* input) {
	printf("TEST BIOS CALL: %x\n", *((uint32_t*) input));

	return 0x89ABCDEF;
}

Instruct speed_test_prgm[] = {
	{DATI,0x1,20},
	{DATI,0x3000000,60},
	{DATI,0x2,15},
	{ADDL,3,20},
	{CMPI,3,60},
	{JILA, 3 * sizeof(Instruct),0},
	{HALT, 0, 0},
};

const char* const tag_test =
	"JMPA [end]\n"
	"ADDI $50 $100\n"
	"MINI $25 $50\n"
	"[end]\n"
	"HALT\n"
	"# EOF\n";

#include <ratio>
#include <chrono>
using namespace std;

int main() {

	printf("===== ASM 76 Test Program =====\n");

	init();

	#define VM_v(var) VM v({.size = sizeof(var), .instruct = var})
	{
		printf("===== Memory =====\n");
		VM v(mem_test_p);
		v.execute(true);
		v.dump_registers();
	}

	{
		printf("===== Basic Algebra =====\n");
		VM_v(basic_algebra_test_prgm);
		v.execute(true);
		v.dump_registers();
	}

	{
		printf("===== Disassembler =====\n");
		Disassembler d({sizeof(flow_control_test_prgm), flow_control_test_prgm});
		char* s = d.disassemble();
		puts(s);
		free(s);
	}

	{
		printf("===== Assembler =====\n");
		Assembler a(asm_test);
		a.scan();
		Program p = a.assemble();
		// Test assembler DD function
		printf("Data DD: %04x%08x%08x\n", p.instruct[9].opcode, p.instruct[9].a, p.instruct[9].b);
		// Test disassembler
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);

		printf("===== Flow Control & Logistics =====\n");
		VM v(p);
		v.execute(false);
		v.dump_registers();
		free(p.instruct);
	}

	{
		printf("===== Assembler: Tag Test =====\n");
		Assembler a(tag_test);
		a.scan();
		Program p = a.assemble();
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);
	}

	{
		printf("===== BIOS Test =====\n");
		BIOS* b = new BIOS(5);
		b->function_table[1] = &test_bios_call;

		Assembler a(bios_test);
		a.scan();
		Program p = a.assemble();

		VM v(p);
		v.firmware = b;
		v.execute(true);
		v.dump_registers();
	}

	{
		printf("===== Object Code =====\n");
		ObjectCode::write_file("test.obj", mem_test_p);
		Program p = ObjectCode::read_file("test.obj");
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);
		free(p.instruct);
	}

	{
		printf("===== Speed Test: 0x3000000 cycles =====\n");
		VM_v(speed_test_prgm);

		// The type is chrono::time_point<chrono::high_resolution_clock>
		// and that is why people used auto.
		auto t1 = chrono::high_resolution_clock::now();
		v.execute(false);
		auto t2 = chrono::high_resolution_clock::now();
		chrono::duration<double, milli> delay = t2 - t1;
		printf("Elapsed time: %lfms\nMIPS: %lf\n",
			delay.count(),
			((double) 0x3000000) * 3.0 / ((double) delay.count()) / 10000.0
		);
	}

	printf("===== TEST END =====\n");

	return 0;
}
<commit_msg>Refine VMtest.cxx<commit_after>//=============================================================================
// ■ VMtest.cxx
//-----------------------------------------------------------------------------
//   虚拟机测试程序。
//   扩展名用了.cxx，意思是“×不要自动编译”。
//=============================================================================

#include <ratio>
#include <chrono>
using namespace std;

#include "ASM76.hpp"
using namespace ASM76;

Instruct test_mem_i[] = {
	{LCMM, 0x4000000, 0},
	{DATI, 0xABCD1234, 1},
	{DATB, 'V', 5},
	{DATB, 'M', 6},
	{DATB, '7', 7},
	{DATB, '6', 8},
	{SLLA, 0x2000000, 1},
	{SLIA, 0x2500000, 2},
	{SLBA, 0x2700000, 3},
	{LDLA, 0x2500000, 51},
	{LDIA, 0x2500000, 51},
	{LDBA, 0x2500000, 61},
	{HALT, 0, 0},
};
Program test_mem_p {
	.size = sizeof(test_mem_i),
	.instruct = test_mem_i
};

Instruct test_basic_algebra_i[] = {
	{LCMM, 0x100, 0},
	{DATI, 0x1, 1},
	// $1 = $1 + $1
	// 1, 2, 4, 8, 16, ...
	{ADDL, 1, 1},
	{ADDL, 1, 1},
	{ADDL, 1, 1},
	{ADDL, 1, 1},
	// Put the result somewhere else
	{MVRL, 1, 31},
	// Then divide it by 4
	{DATI, 0x4, 11},
	{DIVL, 1, 11},
	{HALT, 0, 0},
};
Program test_basic_algebra_p {
	.size = sizeof(test_basic_algebra_i),
	.instruct = test_basic_algebra_i
};

Instruct test_flow_control_i[] = {
	{DATB, 0x1, 20},
	{DATB, 0xA, 10},
	{DATB, 0x2, 15},
	{ADDL, 15, 15},
	{ADDL, 3, 20},
	{CMPI, 3, 10},
	{PUSH, 15, 1},
	{JILA, 3 * sizeof(Instruct), 0},
	{HALT, 0, 0},
};
Program test_flow_control_p {
	.size = sizeof(test_flow_control_i),
	.instruct = test_flow_control_i
};

const char* const test_asm =
	"# Comments.\n"
	"DATB	0x1 $20\n"
	"DATB	0xA $10\n"
	"DATB	0x2 $15\n"
	"[loop_start]\n"
	"ADDL	$15 $15\n"
	"ADDL	$3 $20\n"
	"CMPI	$3 $10\n"
	"PUSH	$15 1\n"
	"JILA	[loop_start]\n"
	"HALT\n"
	"DD 0x7676 0xEFEF 0xABAB 0xCDCD 0x0000\n"
	"# EOF\n";

const char* const test_bios =
	"DATI	0x76 $0\n"
	"SLIA	0x100 $0\n"
	"INTX	0x1 0x100\n"
	"DATI	0xAB $0\n"
	"SLIA	0x100 $0\n"
	"INTX	0x1 0x100\n"
	"HALT\n"
	"# EOF\n";

static uint32_t test_bios_call(uint8_t* input) {
	printf("TEST BIOS CALL: %x\n", *((uint32_t*) input));

	return 0x89ABCDEF;
}

Instruct test_speed_i[] = {
	{DATI, 0x1, 20},
	{DATI, 0x3000000, 60},
	{DATI, 0x2, 15},
	{ADDL, 3, 20},
	{CMPI, 3, 60},
	{JILA, 3 * sizeof(Instruct), 0},
	{HALT, 0, 0},
};
Program test_speed_p {
	.size = sizeof(test_speed_i),
	.instruct = test_speed_i
};

const char* const test_tag =
	"JMPA [end]\n"
	"ADDI $50 $100\n"
	"MINI $25 $50\n"
	"[end]\n"
	"HALT\n"
	"# EOF\n";

int main() {
	puts("+---------------------+");
	puts("| ASM 76 Test Program |");
	puts("+---------------------+");
	init();

	{
		puts("===== Memory =====");
		VM v(test_mem_p);
		v.execute(true);
		v.dump_registers();
	}

	{
		puts("===== Basic Algebra =====");
		VM v(test_basic_algebra_p);
		v.execute(true);
		v.dump_registers();
	}

	{
		puts("===== Disassembler =====");
		Disassembler d(test_flow_control_p);
		char* s = d.disassemble();
		puts(s);
		free(s);
	}

	{
		puts("===== Assembler =====");
		Assembler a(test_asm);
		a.scan();
		Program p = a.assemble();
		// Test assembler DD function
		printf("Data DD: %04x%08x%08x\n", p.instruct[9].opcode, p.instruct[9].a, p.instruct[9].b);
		// Test disassembler
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);

		puts("===== Flow Control & Logistics =====");
		VM v(p);
		v.execute(false);
		v.dump_registers();
		free(p.instruct);
	}

	{
		puts("===== Assembler: Tag Test =====");
		Assembler a(test_tag);
		a.scan();
		Program p = a.assemble();
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);
	}

	{
		puts("===== BIOS Test =====");
		BIOS* b = new BIOS(5);
		b->function_table[1] = &test_bios_call;

		Assembler a(test_bios);
		a.scan();
		Program p = a.assemble();

		VM v(p);
		v.firmware = b;
		v.execute(true);
		v.dump_registers();
	}

	{
		puts("===== Object Code =====");
		ObjectCode::write_file("test.obj", test_mem_p);
		Program p = ObjectCode::read_file("test.obj");
		Disassembler d(p);
		char* s = d.disassemble();
		puts(s);
		free(s);
		free(p.instruct);
	}

	{
		puts("===== Speed Test: 0x3000000 cycles =====");
		VM v(test_speed_p);

		// The type is chrono::time_point<chrono::high_resolution_clock>
		// and that is why people used auto.
		auto t1 = chrono::high_resolution_clock::now();
		v.execute(false);
		auto t2 = chrono::high_resolution_clock::now();
		chrono::duration<double, milli> delay = t2 - t1;
		printf("Elapsed time: %lfms\nMIPS: %lf\n",
			delay.count(),
			((double) 0x3000000) * 3.0 / ((double) delay.count()) / 10000.0
		);
	}

	puts("\n===== TEST END =====");

	return 0;
}
<|endoftext|>


<commit_before>#include "ApacheProcess.h"

#include "ApacheRequest.h"

namespace mod_node {

    static apr_queue_t *queue;
    static ev_async req_watcher;

    static Persistent<Object> Process;
    static Persistent<Function> ProcessFunc;

    static Persistent<String> onrequest_sym;

    static process_rec *process;

    static void node_hook_child_init(apr_pool_t *p, server_rec *s);

    void ApacheProcess::Initialize(Handle<Object> target) {
        using mod_node::process;
        using mod_node::queue;
        using mod_node::req_watcher;
        HandleScope scope;

        Local<FunctionTemplate> proc_function_template = FunctionTemplate::New();
        proc_function_template->InstanceTemplate()->SetInternalFieldCount(1);
        proc_function_template->SetClassName(String::New("ApacheProcess"));

        NODE_SET_PROTOTYPE_METHOD(proc_function_template, "log", Log);

        target->Set(String::New("APLOG_EMERG"), v8::Integer::NewFromUnsigned(APLOG_EMERG));
        target->Set(String::New("APLOG_ALERT"), v8::Integer::NewFromUnsigned(APLOG_ALERT));
        target->Set(String::New("APLOG_CRIT"), v8::Integer::NewFromUnsigned(APLOG_CRIT));
        target->Set(String::New("APLOG_ERR"), v8::Integer::NewFromUnsigned(APLOG_ERR));
        target->Set(String::New("APLOG_WARNING"), v8::Integer::NewFromUnsigned(APLOG_WARNING));
        target->Set(String::New("APLOG_INFO"), v8::Integer::NewFromUnsigned(APLOG_INFO));
        target->Set(String::New("APLOG_NOTICE"), v8::Integer::NewFromUnsigned(APLOG_NOTICE));
        target->Set(String::New("APLOG_DEBUG"), v8::Integer::NewFromUnsigned(APLOG_DEBUG));

        onrequest_sym = NODE_PSYMBOL("onrequest");

        ProcessFunc = Persistent<Function>::New(proc_function_template->GetFunction());
        Process = Persistent<Object>::New(ProcessFunc->NewInstance());

        apr_queue_create(&queue, 100, process->pool); // @todo handle error
        ev_async_init(EV_DEFAULT_UC_ &req_watcher, ApacheProcess::RequestCallback);
        ev_async_start(EV_DEFAULT_UC_ &req_watcher);
        ev_ref(EV_DEFAULT_UC);

        target->Set(String::New("ApacheProcess"), ProcessFunc);
        target->Set(String::New("process"), Process);
    }

    void ApacheProcess::register_hooks(apr_pool_t *p) {
        ap_hook_child_init (node_hook_child_init, NULL,NULL, APR_HOOK_MIDDLE);
        ap_hook_handler(ApacheProcess::handler, NULL, NULL, APR_HOOK_MIDDLE);
    };

    int ApacheProcess::handler(request_rec *r) {
        // Runs in the Apache thread
        using mod_node::queue;
        using mod_node::req_watcher;

        apr_status_t rv;
        request_ext rex;
        rex.req = r;
        rex.cont_request = 0;
        int rc = OK;
        apr_thread_cond_create(&rex.cv, process->pool);
        apr_thread_mutex_create(&rex.mtx, APR_THREAD_MUTEX_DEFAULT,  process->pool);

        apr_thread_mutex_lock(rex.mtx);
        apr_table_setn(r->notes, "mod_node", (char *)&rex);
        apr_queue_push(queue, &rex); // @todo Errors
        {
            ev_async_send(EV_DEFAULT_ &req_watcher);
            while(!rex.cont_request) {
                apr_thread_cond_wait(rex.cv, rex.mtx);
            }
        }
        apr_thread_mutex_unlock(rex.mtx);

        return rc;
    }

    void ApacheProcess::RequestCallback(EV_P_ ev_async *w, int revents) {
        // Executes in Node's thread
        using mod_node::queue;
        using mod_node::req_watcher;

        HandleScope scope;
        request_ext *rex;
        apr_queue_pop(queue, (void **)&rex); // @todo Errors
        Handle<Value> req = ApacheRequest::New(rex);
        Local<Value> callback_v = Process->Get(onrequest_sym);
        if(!callback_v->IsFunction()) return;
        TryCatch trycatch;
        trycatch.SetVerbose(true);
        trycatch.SetCaptureMessage(true);
        const int argc = 1;
        Handle<Value> args[argc] = { req };
        Local<Function>::Cast(callback_v)->Call(Process, 1, args);
        if(trycatch.HasCaught()) {
            v8::String::Utf8Value str(trycatch.Message()->Get());
            ap_log_perror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, process->pool, "%s", *str);
        }

    };

    Handle<Value> ApacheProcess::Log(const Arguments &args) {
        if (args.Length() < 2 || !args[1]->IsString() || !args[0]->IsInt32()) {
            return THROW_BAD_ARGS;
        }
        String::Utf8Value val(args[1]->ToString());
        ap_log_perror(APLOG_MARK, args[0]->ToInt32()->Value(), APR_SUCCESS, process->pool, "%s", *val);
        return Undefined();
    };

    static void node_hook_child_init(apr_pool_t *p, server_rec *s) {
        using mod_node::thread;
        using mod_node::process;
        ap_open_logs(p, p, p, s);
        mod_node::process = s->process;
        apr_thread_create(&mod_node::thread, NULL, start_node, (void *)s, s->process->pool);
    };

};
<commit_msg>Use trypop and a loop, so we can be more out of sync with Apache<commit_after>#include "ApacheProcess.h"

#include "ApacheRequest.h"

namespace mod_node {

    static apr_queue_t *queue;
    static ev_async req_watcher;

    static Persistent<Object> Process;
    static Persistent<Function> ProcessFunc;

    static Persistent<String> onrequest_sym;

    static process_rec *process;

    static void node_hook_child_init(apr_pool_t *p, server_rec *s);

    void ApacheProcess::Initialize(Handle<Object> target) {
        using mod_node::process;
        using mod_node::queue;
        using mod_node::req_watcher;
        HandleScope scope;

        Local<FunctionTemplate> proc_function_template = FunctionTemplate::New();
        proc_function_template->InstanceTemplate()->SetInternalFieldCount(1);
        proc_function_template->SetClassName(String::New("ApacheProcess"));

        NODE_SET_PROTOTYPE_METHOD(proc_function_template, "log", Log);

        target->Set(String::New("APLOG_EMERG"), v8::Integer::NewFromUnsigned(APLOG_EMERG));
        target->Set(String::New("APLOG_ALERT"), v8::Integer::NewFromUnsigned(APLOG_ALERT));
        target->Set(String::New("APLOG_CRIT"), v8::Integer::NewFromUnsigned(APLOG_CRIT));
        target->Set(String::New("APLOG_ERR"), v8::Integer::NewFromUnsigned(APLOG_ERR));
        target->Set(String::New("APLOG_WARNING"), v8::Integer::NewFromUnsigned(APLOG_WARNING));
        target->Set(String::New("APLOG_INFO"), v8::Integer::NewFromUnsigned(APLOG_INFO));
        target->Set(String::New("APLOG_NOTICE"), v8::Integer::NewFromUnsigned(APLOG_NOTICE));
        target->Set(String::New("APLOG_DEBUG"), v8::Integer::NewFromUnsigned(APLOG_DEBUG));

        onrequest_sym = NODE_PSYMBOL("onrequest");

        ProcessFunc = Persistent<Function>::New(proc_function_template->GetFunction());
        Process = Persistent<Object>::New(ProcessFunc->NewInstance());

        apr_queue_create(&queue, 100, process->pool); // @todo handle error
        ev_async_init(EV_DEFAULT_UC_ &req_watcher, ApacheProcess::RequestCallback);
        ev_async_start(EV_DEFAULT_UC_ &req_watcher);
        ev_ref(EV_DEFAULT_UC);

        target->Set(String::New("ApacheProcess"), ProcessFunc);
        target->Set(String::New("process"), Process);
    }

    void ApacheProcess::register_hooks(apr_pool_t *p) {
        ap_hook_child_init (node_hook_child_init, NULL,NULL, APR_HOOK_MIDDLE);
        ap_hook_handler(ApacheProcess::handler, NULL, NULL, APR_HOOK_MIDDLE);
    };

    int ApacheProcess::handler(request_rec *r) {
        // Runs in the Apache thread
        using mod_node::queue;
        using mod_node::req_watcher;

        apr_status_t rv;
        request_ext rex;
        rex.req = r;
        rex.cont_request = 0;
        int rc = OK;
        apr_thread_cond_create(&rex.cv, process->pool);
        apr_thread_mutex_create(&rex.mtx, APR_THREAD_MUTEX_DEFAULT,  process->pool);

        apr_thread_mutex_lock(rex.mtx);
        apr_table_setn(r->notes, "mod_node", (char *)&rex);
        apr_queue_push(queue, &rex); // @todo Errors
        {
            ev_async_send(EV_DEFAULT_ &req_watcher);
            while(!rex.cont_request) {
                apr_thread_cond_wait(rex.cv, rex.mtx);
            }
        }
        apr_thread_mutex_unlock(rex.mtx);

        return rc;
    }

    void ApacheProcess::RequestCallback(EV_P_ ev_async *w, int revents) {
        // Executes in Node's thread
        using mod_node::queue;
        using mod_node::req_watcher;

        HandleScope scope;
        request_ext *rex;
        while (apr_queue_trypop(queue, (void **)&rex) == APR_SUCCESS) {
            // @todo Errors
            Handle<Value> req = ApacheRequest::New(rex);
            Local<Value> callback_v = Process->Get(onrequest_sym);
            if(!callback_v->IsFunction()) return;
            TryCatch trycatch;
            trycatch.SetVerbose(true);
            trycatch.SetCaptureMessage(true);
            const int argc = 1;
            Handle<Value> args[argc] = { req };
            Local<Function>::Cast(callback_v)->Call(Process, 1, args);
            if(trycatch.HasCaught()) {
                v8::String::Utf8Value str(trycatch.Message()->Get());
                ap_log_perror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, process->pool, "%s", *str);
            }
        }

    };

    Handle<Value> ApacheProcess::Log(const Arguments &args) {
        if (args.Length() < 2 || !args[1]->IsString() || !args[0]->IsInt32()) {
            return THROW_BAD_ARGS;
        }
        String::Utf8Value val(args[1]->ToString());
        ap_log_perror(APLOG_MARK, args[0]->ToInt32()->Value(), APR_SUCCESS, process->pool, "%s", *val);
        return Undefined();
    };

    static void node_hook_child_init(apr_pool_t *p, server_rec *s) {
        using mod_node::thread;
        using mod_node::process;
        ap_open_logs(p, p, p, s);
        mod_node::process = s->process;
        apr_thread_create(&mod_node::thread, NULL, start_node, (void *)s, s->process->pool);
    };

};
<|endoftext|>


<commit_before>/*
 * opencog/atoms/base/Atom.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * Written by Thiago Maia <thiago@vettatech.com>
 *            Andre Senna <senna@vettalabs.com>
 *            Welter Silva <welter@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/AtomTable.h>
#include <opencog/attentionbank/AttentionBank.h>
#include <opencog/attentionbank/ImportanceIndex.h>

namespace opencog {

#define _avmtx _mtx

// ==============================================================

AttentionValuePtr Atom::getAttentionValue() const
{
    // OK. The atomic thread-safety of shared-pointers is subtle. See
    // http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety
    // and http://cppwisdom.quora.com/shared_ptr-is-almost-thread-safe
    // What it boils down to here is that we must *always* make a copy
    // of _attentionValue before we use it, since it can go out of scope
    // because it can get set in another thread.  Viz, using it to
    // dereference can return a raw pointer to an object that has been
    // deconstructed. Furthermore, we must make a copy while holding
    // the lock! Got that?

    std::lock_guard<std::mutex> lck(_mtx);
    AttentionValuePtr local(_attentionValue);
    return local;
}

// XXX TODO This is insane. All this needs to be moved to the attention bank.
void Atom::setAttentionValue(AttentionValuePtr av)
{
    // Must obtain a local copy of the AV, since there may be
    // parallel writers in other threads.
    AttentionValuePtr local(getAttentionValue());
    if (av == local) return;
    if (*av == *local) return;

    // Need to lock, shared_ptr is NOT atomic!
    std::unique_lock<std::mutex> lck (_avmtx);
    local = _attentionValue; // Get it again, to avoid races.
    _attentionValue = av;
    lck.unlock();

    // If the atom free-floating, we are done.
    if (NULL == _atomTable) return;

    // Get old and new bins.
    int oldBin = ImportanceIndex::importanceBin(local->getSTI());
    int newBin = ImportanceIndex::importanceBin(av->getSTI());

    // If the atom importance has changed its bin,
    // update the importance index.
    if (oldBin != newBin) {
        attentionbank(_atomTable->getAtomSpace()).updateImportanceIndex(getHandle(), oldBin);
    }

    // Notify any interested parties that the AV changed.
    AVCHSigl& avch = attentionbank(_atomTable->getAtomSpace()).getAVChangedSignal();
    avch(getHandle(), local, av);
}

void Atom::chgVLTI(int unit)
{
    AttentionValuePtr old_av = getAttentionValue();
    AttentionValuePtr new_av = createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);
    setAttentionValue(new_av);
}

// ==============================================================

} // ~namespace opencog
<commit_msg>Remove the AV from the atom.<commit_after>/*
 * opencog/atoms/base/Atom.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * Written by Thiago Maia <thiago@vettatech.com>
 *            Andre Senna <senna@vettalabs.com>
 *            Welter Silva <welter@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/AtomTable.h>
#include <opencog/attentionbank/AttentionBank.h>
#include <opencog/attentionbank/ImportanceIndex.h>

namespace opencog {

#define _avmtx _mtx

// ==============================================================

AttentionValuePtr Atom::getAttentionValue() const
{
    if (NULL == _atomTable) return AttentionValue::DEFAULT_AV();
    Atom* a = (Atom*) this;
    return attentionbank(_atomTable->getAtomSpace()).get_av(a->getHandle());
}

// XXX TODO This is insane. All this needs to be moved to the attention bank.
void Atom::setAttentionValue(AttentionValuePtr av)
{
    // If the atom free-floating, we are done.
    if (NULL == _atomTable) return;

    AttentionValuePtr local(getAttentionValue());
    attentionbank(_atomTable->getAtomSpace()).add_atom(getHandle(), av);

    // Get old and new bins.
    int oldBin = ImportanceIndex::importanceBin(local->getSTI());
    int newBin = ImportanceIndex::importanceBin(av->getSTI());

    // If the atom importance has changed its bin,
    // update the importance index.
    if (oldBin != newBin) {
        attentionbank(_atomTable->getAtomSpace()).updateImportanceIndex(getHandle(), oldBin);
    }

    // Notify any interested parties that the AV changed.
    AVCHSigl& avch = attentionbank(_atomTable->getAtomSpace()).getAVChangedSignal();
    avch(getHandle(), local, av);
}

void Atom::chgVLTI(int unit)
{
    AttentionValuePtr old_av = getAttentionValue();
    AttentionValuePtr new_av = createAV(
        old_av->getSTI(),
        old_av->getLTI(),
        old_av->getVLTI() + unit);
    setAttentionValue(new_av);
}

// ==============================================================

} // ~namespace opencog
<|endoftext|>