<commit_before>#ifndef _TOOLBOX_CURL_EASY_HPP_
#define _TOOLBOX_CURL_EASY_HPP_

#include <curl/curl.h>
#include <tuple>
#include <vector>
#include <string>
#include <toolbox/cpp/tuple_for_each.hpp>
#include <toolbox/curl/curl_error.hpp>

namespace toolbox
{
namespace curl
{

namespace options
{

namespace detail
{

template<typename T>
struct curl_type
{
	curl_type (const T &value) :
		value_ (value)
	{}

	using curl_type_t = T;
	using cpp_type_t = T;

	curl_type_t curl_value() const
	{
		return value_;
	}

	T value_;
};

template<> struct curl_type<std::string>
{
	curl_type (const std::string &value) :
		value_ (value)
	{
	}

	curl_type(curl_type<std::string> &&rhs) = default;
	curl_type(const curl_type<std::string> &) = delete;
	void operator=(const curl_type<std::string> &) = delete;

	using curl_type_t = const char *;
	using cpp_type_t = std::string;

	curl_type_t curl_value() const
	{
		return value_.c_str();
	}

	cpp_type_t value_;
};

template<> struct curl_type<std::vector<std::string>>
{
	using curl_type_t = curl_slist *;
	using cpp_type_t = std::vector<std::string>;

	curl_type (const std::vector<std::string> &value)
	{
		for (auto &el : value)
			value_ = curl_slist_append(value_, el.c_str());
	}

	curl_type(curl_type<cpp_type_t> &&rhs)
	{
		std::swap(value_, rhs.value_);
	}

	curl_type(const curl_type<cpp_type_t> &) = delete;
	void operator=(curl_type<cpp_type_t> &) = delete;

	~curl_type()
	{
		curl_slist_free_all(value_);
	}

	curl_type_t curl_value() const
	{
		return value_;
	}

private:
	curl_type_t value_ = nullptr;
};

} // namespacec detail

template<int E, typename T>
struct option_def
{
	using type_t = T;
	static constexpr auto option = static_cast<CURLoption>(E);

	option_def(const T &value) :
		value_ (value) {}

	option_def(option_def<E, T> &&rhs) :
		value_ (std::move(rhs.value_))
	{}

	auto value() const
	{
		return value_.curl_value();
	}

private:
	detail::curl_type<T> value_;
};

using verbose = option_def<CURLOPT_VERBOSE, long>;
using url = option_def<CURLOPT_URL, std::string>;
using postfields = option_def<CURLOPT_POSTFIELDS, std::string>;
using writefunction = option_def<CURLOPT_WRITEFUNCTION, size_t(*)(char *, size_t, size_t, void *)>;
using writedata = option_def<CURLOPT_WRITEDATA, void *>;
using httpheader = option_def<CURLOPT_HTTPHEADER, std::vector<std::string>>;

} // namespace options

template<typename Options>
class easy
{
public:
	easy(Options &&options) :
		curl_ (curl_easy_init()),
		options_ (std::move(options))
	{
		cpp::tuple_for_each(
			options_,
			[this](const auto &option) {
				auto res = curl_easy_setopt(curl_, std::decay<decltype(option)>::type::option, option.value());

				if (res != CURLE_OK)
					throw curl_error(res, "curl_easy_setopt failed");
			}
		);
	}

	easy(easy<Options> &&rhs) :
		curl_ (rhs.curl_),
		options_ (std::move(rhs.options_))
	{
		rhs.curl_ = nullptr;
	}

	void operator=(easy &&rhs)
	{
		curl_ = rhs.curl_;
		options_ = std::move(rhs.options_);
		rhs.curl_ = nullptr;
	}

	easy(const easy &) = delete;
	void operator=(const easy &) = delete;

	CURLcode perform() const
	{
		return curl_easy_perform(curl_);
	}

	~easy()
	{
		if (curl_)
			curl_easy_cleanup (curl_);
	}

private:
	CURL* curl_ = nullptr;
	Options options_;
};

template<typename... Options>
auto make_easy(Options&& ... options)
{
	return easy<std::tuple<Options...>>(std::tuple<Options...>(std::forward<Options>(options)...));
}

} // namespace curl
} // namespace toolbox

#endif
<commit_msg>retab<commit_after>#ifndef _TOOLBOX_CURL_EASY_HPP_
#define _TOOLBOX_CURL_EASY_HPP_

#include <curl/curl.h>
#include <tuple>
#include <vector>
#include <string>
#include <toolbox/cpp/tuple_for_each.hpp>
#include <toolbox/curl/curl_error.hpp>

namespace toolbox
{
namespace curl
{

namespace options
{

namespace detail
{

template<typename T>
struct curl_type
{
    curl_type (const T &value) :
        value_ (value)
    {}

    using curl_type_t = T;
    using cpp_type_t = T;

    curl_type_t curl_value() const
    {
        return value_;
    }

    T value_;
};

template<> struct curl_type<std::string>
{
    curl_type (const std::string &value) :
        value_ (value)
    {
    }

    curl_type(curl_type<std::string> &&rhs) = default;
    curl_type(const curl_type<std::string> &) = delete;
    void operator=(const curl_type<std::string> &) = delete;

    using curl_type_t = const char *;
    using cpp_type_t = std::string;

    curl_type_t curl_value() const
    {
        return value_.c_str();
    }

    cpp_type_t value_;
};

template<> struct curl_type<std::vector<std::string>>
{
    using curl_type_t = curl_slist *;
    using cpp_type_t = std::vector<std::string>;

    curl_type (const std::vector<std::string> &value)
    {
        for (auto &el : value)
            value_ = curl_slist_append(value_, el.c_str());
    }

    curl_type(curl_type<cpp_type_t> &&rhs)
    {
        std::swap(value_, rhs.value_);
    }

    curl_type(const curl_type<cpp_type_t> &) = delete;
    void operator=(curl_type<cpp_type_t> &) = delete;

    ~curl_type()
    {
        curl_slist_free_all(value_);
    }

    curl_type_t curl_value() const
    {
        return value_;
    }

private:
    curl_type_t value_ = nullptr;
};

} // namespacec detail

template<int E, typename T>
struct option_def
{
    using type_t = T;
    static constexpr auto option = static_cast<CURLoption>(E);

    option_def(const T &value) :
        value_ (value) {}

    option_def(option_def<E, T> &&rhs) :
        value_ (std::move(rhs.value_))
    {}

    auto value() const
    {
        return value_.curl_value();
    }

private:
    detail::curl_type<T> value_;
};

using verbose = option_def<CURLOPT_VERBOSE, long>;
using url = option_def<CURLOPT_URL, std::string>;
using postfields = option_def<CURLOPT_POSTFIELDS, std::string>;
using writefunction = option_def<CURLOPT_WRITEFUNCTION, size_t(*)(char *, size_t, size_t, void *)>;
using writedata = option_def<CURLOPT_WRITEDATA, void *>;
using httpheader = option_def<CURLOPT_HTTPHEADER, std::vector<std::string>>;

} // namespace options

template<typename Options>
class easy
{
public:
    easy(Options &&options) :
        curl_ (curl_easy_init()),
        options_ (std::move(options))
    {
        cpp::tuple_for_each(
            options_,
            [this](const auto &option) {
                auto res = curl_easy_setopt(curl_, std::decay<decltype(option)>::type::option, option.value());

                if (res != CURLE_OK)
                    throw curl_error(res, "curl_easy_setopt failed");
            }
        );
    }

    easy(easy<Options> &&rhs) :
        curl_ (rhs.curl_),
        options_ (std::move(rhs.options_))
    {
        rhs.curl_ = nullptr;
    }

    void operator=(easy &&rhs)
    {
        curl_ = rhs.curl_;
        options_ = std::move(rhs.options_);
        rhs.curl_ = nullptr;
    }

    easy(const easy &) = delete;
    void operator=(const easy &) = delete;

    CURLcode perform() const
    {
        return curl_easy_perform(curl_);
    }

    ~easy()
    {
        if (curl_)
            curl_easy_cleanup (curl_);
    }

private:
    CURL* curl_ = nullptr;
    Options options_;
};

template<typename... Options>
auto make_easy(Options&& ... options)
{
    return easy<std::tuple<Options...>>(std::tuple<Options...>(std::forward<Options>(options)...));
}

} // namespace curl
} // namespace toolbox

#endif
<|endoftext|>


<commit_before>#include "subhmm_messages.h"

using namespace Eigen;
using namespace std;
using namespace subhmm;

inline
float subhmm::just_fast_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        NPMatrix &esuper_trans,
        vector<NPMatrix> &esub_transs, vector<NPVector> &esub_inits,
        int *blocksizes, int *blockstarts,
        float *v, float *out)
{
    // these two lines just force eincomings to be on the stack
    float incomings[N]; // NOTE: assuming stack pointer alignment for this guy too
    NPVector eincomings(incomings,N);

    float sum_of_result = 0.;

    // NOTE: the next two loops are each parallelizeable over N

    for (int i=0; i<N; i++) {
        eincomings(i) = esub_inits[i].dot(NPSubVector(v + blockstarts[i],Nsubs[i]));
    }

    #ifdef _OPENMP
    #pragma omp parallel for
    #endif
    for (int i=0; i < N; i++) {
        int blockstart = blockstarts[i];
        int blocksize = blocksizes[i];
        int32_t Nsub = Nsubs[i];
        int32_t r = rs[i];
        float p = ps[i];
        NPMatrix &subtrans = esub_transs[i];

        NPSubMatrix rv(v + blockstart,r,Nsub);
        NPSubMatrix rout(out + blockstart,r,Nsub);

        // within-block
        MatrixXf temp(r,Nsub); // NOTE: checked asm, no malloc here with g++ -O3, note float
        temp = rv * subtrans.transpose();
        rout = (temp.array() * (1-p)).matrix();
        rout.block(0,0,r-1,Nsub) += p * temp.block(1,0,r-1,Nsub);

        // across-block
        NPSubVectorArray(out+blockstart+blocksize-Nsub,Nsub)
            += p * esuper_trans.row(i).dot(eincomings);

        // track sum
        sum_of_result += rout.sum();
    }

    return sum_of_result;
}

inline
float subhmm::just_fast_left_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        NPMatrix &esuper_trans_T,
        vector<NPMatrix> &esub_transs, vector<NPVector> &esub_inits,
        int *blocksizes, int *blockstarts,
        float *v, float *out)
{
    // these two lines just force eincomings to be on the stack
    float incomings[N]; // NOTE: assuming stack pointer alignment for this guy too
    NPVector eincomings(incomings,N);

    float sum_of_result = 0.;

    // NOTE: the next two loops are each parallelizeable over N

    for (int i=0; i<N; i++) {
        incomings[i] = ps[i] * NPSubVector(
                v + blockstarts[i] + blocksizes[i] - Nsubs[i],Nsubs[i]).sum();
    }

    for (int i=0; i < N; i++) {
        int blockstart = blockstarts[i];
        int32_t Nsub = Nsubs[i];
        int32_t r = rs[i];
        float p = ps[i];
        NPMatrix &subtrans = esub_transs[i];
        NPVector &pi = esub_inits[i];

        NPSubMatrix rv(v + blockstart,r,Nsub);
        NPSubMatrix rout(out + blockstart,r,Nsub);

        // within-block
        MatrixXf temp(r,Nsub); // NOTE: checked asm, no malloc here with g++ -O3, note float
        temp = rv * subtrans;
        rout = (temp.array() * (1-p)).matrix();
        rout.block(1,0,r-1,Nsub) += p * temp.block(0,0,r-1,Nsub);

        // across-block
        NPSubVector(out+blockstart,Nsub)
            += (esuper_trans_T.row(i).dot(eincomings)) * pi;

        // track sum
        sum_of_result += rout.sum();
    }

    return sum_of_result;
}

float subhmm::messages_backwards_normalized(
        int T, int bigN, int N, int32_t *Nsubs,
        int32_t *rs, float *ps, float *super_trans, float *init_state_distn,
        std::vector<float*>& sub_transs, std::vector<float*>& sub_inits,
        std::vector<float*>& aBls,
        float *betan)
{
    float temp[bigN];
    NPVectorArray etemp(temp,bigN);

    NPMatrix esuper_trans(super_trans,N,N);

    int blocksizes[N];
    int blockstarts[N];

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    vector<NPArray> eaBls;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
        eaBls.push_back(NPArray(aBls[i],T,Nsubs[i]));
    }
    NPArray ebetan(betan,T,bigN);

    ebetan.row(T-1).setOnes();
    float logtot = 0., cmax;
    for (int t=T-2; t>=0; t--) {
        cmax = -1.*numeric_limits<float>::infinity();
        for (int i=0; i<N; i++) {
            cmax = max(cmax, eaBls[i].row(t+1).maxCoeff());
        }

        for (int i=0; i<N; i++) {
            NPSubArray(temp + blockstarts[i],rs[i],Nsubs[i]).rowwise()
                = (eaBls[i].row(t+1) - cmax).exp();
        }
        etemp *= ebetan.row(t+1);

        float tot = just_fast_mult(N,Nsubs,rs,ps,esuper_trans,
                esub_transs,esub_inits,blocksizes,blockstarts,
                temp,betan + bigN*t);
        ebetan.row(t) /= tot;

        logtot += cmax + log(tot);
    }

    // NOTE: all this stuff is necessary to compute the log likelihood including
    // the initial state distribution

    float in_potential[bigN];
    memset(in_potential,0,sizeof(in_potential));
    cmax = -1.*numeric_limits<float>::infinity();
    for (int i=0; i<N; i++) {
        cmax = max(cmax, eaBls[i].row(0).maxCoeff());
    }
    for (int i=0; i<N; i++) {
        NPSubVectorArray(in_potential + blockstarts[i],Nsubs[i]) =
            init_state_distn[i] * esub_inits[i].array() * (eaBls[i].row(0) - cmax).exp().transpose();
    }
    logtot += cmax + log((NPVectorArray(in_potential,bigN) * ebetan.row(0).transpose()).sum());

    return logtot;
}

float subhmm::messages_forwards_normalized(
        int T, int bigN, int N, int32_t *Nsubs,
        int32_t *rs, float *ps, float *super_trans, float *init_state_distn,
        std::vector<float*>& sub_transs, std::vector<float*>& sub_inits,
        std::vector<float*>& aBls,
        float *alphan)
{
    float in_potential[bigN] __attribute__ ((aligned(16)));
    int blocksizes[N];
    int blockstarts[N];
    NPMatrix esuper_trans_T(super_trans,N,N);
    esuper_trans_T.transposeInPlace();

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    vector<NPArray> eaBls;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
        eaBls.push_back(NPArray(aBls[i],T,Nsubs[i]));
    }
    NPArray ealphan(alphan,T,bigN);

    NPVectorArray ein_potential(in_potential,bigN);
    ein_potential.setZero();
    for (int i=0; i<N; i++) {
        ein_potential.segment(blockstarts[i],Nsubs[i]) =
            init_state_distn[i] * esub_inits[i].array();
    }
    float logtot = 0., cmax;
    for (int t=0; t<T; t++) {
        cmax = -1.*numeric_limits<float>::infinity();
        for (int i=0; i<N; i++) {
            cmax = max(cmax, eaBls[i].row(t).maxCoeff());
        }

        for (int i=0; i<N; i++) {
            NPSubArray(in_potential + blockstarts[i],rs[i],Nsubs[i]).rowwise()
                *= (eaBls[i].row(t) - cmax).exp();
        }
        float tot = ein_potential.sum();
        ealphan.row(t) = ein_potential / tot;
        logtot += log(tot) + cmax;

        just_fast_left_mult(N,Nsubs,rs,ps,esuper_trans_T,
                esub_transs,esub_inits,blocksizes,blockstarts,
                alphan + bigN*t,in_potential);
    }
    return logtot;
}

// these next ones are for testing

void subhmm::fast_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        float *super_trans, vector<float*>& sub_transs, vector<float*>& sub_inits,
        float *v, float *out)
{
    // prep work!
    int blocksizes[N];
    int blockstarts[N];
    NPMatrix esuper_trans(super_trans,N,N);

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
    }

    just_fast_mult(N, Nsubs, rs, ps, esuper_trans, esub_transs, esub_inits,
            blocksizes, blockstarts,
            v, out);
}

void subhmm::fast_left_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        float *super_trans, vector<float*>& sub_transs, vector<float*>& sub_inits,
        float *v, float *out)
{
    // prep work!
    int blocksizes[N];
    int blockstarts[N];

    float super_trans_T[N*N];
    NPMatrix esuper_trans_T(super_trans_T,N,N);
    esuper_trans_T = NPMatrix(super_trans,N,N).transpose();

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
    }

    just_fast_left_mult(N, Nsubs, rs, ps, esuper_trans_T, esub_transs, esub_inits,
            blocksizes, blockstarts,
            v, out);
}

<commit_msg>added another alignment directive<commit_after>#include "subhmm_messages.h"

using namespace Eigen;
using namespace std;
using namespace subhmm;

inline
float subhmm::just_fast_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        NPMatrix &esuper_trans,
        vector<NPMatrix> &esub_transs, vector<NPVector> &esub_inits,
        int *blocksizes, int *blockstarts,
        float *v, float *out)
{
    // these two lines just force eincomings to be on the stack
    float incomings[N]; // NOTE: assuming stack pointer alignment for this guy too
    NPVector eincomings(incomings,N);

    float sum_of_result = 0.;

    // NOTE: the next two loops are each parallelizeable over N

    for (int i=0; i<N; i++) {
        eincomings(i) = esub_inits[i].dot(NPSubVector(v + blockstarts[i],Nsubs[i]));
    }

    #ifdef _OPENMP
    #pragma omp parallel for
    #endif
    for (int i=0; i < N; i++) {
        int blockstart = blockstarts[i];
        int blocksize = blocksizes[i];
        int32_t Nsub = Nsubs[i];
        int32_t r = rs[i];
        float p = ps[i];
        NPMatrix &subtrans = esub_transs[i];

        NPSubMatrix rv(v + blockstart,r,Nsub);
        NPSubMatrix rout(out + blockstart,r,Nsub);

        // within-block
        MatrixXf temp(r,Nsub); // NOTE: checked asm, no malloc here with g++ -O3, note float
        temp = rv * subtrans.transpose();
        rout = (temp.array() * (1-p)).matrix();
        rout.block(0,0,r-1,Nsub) += p * temp.block(1,0,r-1,Nsub);

        // across-block
        NPSubVectorArray(out+blockstart+blocksize-Nsub,Nsub)
            += p * esuper_trans.row(i).dot(eincomings);

        // track sum
        sum_of_result += rout.sum();
    }

    return sum_of_result;
}

inline
float subhmm::just_fast_left_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        NPMatrix &esuper_trans_T,
        vector<NPMatrix> &esub_transs, vector<NPVector> &esub_inits,
        int *blocksizes, int *blockstarts,
        float *v, float *out)
{
    // these two lines just force eincomings to be on the stack
    float incomings[N] __attribute__ ((aligned(16)));
    NPVector eincomings(incomings,N);

    float sum_of_result = 0.;

    // NOTE: the next two loops are each parallelizeable over N

    for (int i=0; i<N; i++) {
        incomings[i] = ps[i] * NPSubVector(
                v + blockstarts[i] + blocksizes[i] - Nsubs[i],Nsubs[i]).sum();
    }

    for (int i=0; i < N; i++) {
        int blockstart = blockstarts[i];
        int32_t Nsub = Nsubs[i];
        int32_t r = rs[i];
        float p = ps[i];
        NPMatrix &subtrans = esub_transs[i];
        NPVector &pi = esub_inits[i];

        NPSubMatrix rv(v + blockstart,r,Nsub);
        NPSubMatrix rout(out + blockstart,r,Nsub);

        // within-block
        MatrixXf temp(r,Nsub); // NOTE: checked asm, no malloc here with g++ -O3, note float
        temp = rv * subtrans;
        rout = (temp.array() * (1-p)).matrix();
        rout.block(1,0,r-1,Nsub) += p * temp.block(0,0,r-1,Nsub);

        // across-block
        NPSubVector(out+blockstart,Nsub)
            += (esuper_trans_T.row(i).dot(eincomings)) * pi;

        // track sum
        sum_of_result += rout.sum();
    }

    return sum_of_result;
}

float subhmm::messages_backwards_normalized(
        int T, int bigN, int N, int32_t *Nsubs,
        int32_t *rs, float *ps, float *super_trans, float *init_state_distn,
        std::vector<float*>& sub_transs, std::vector<float*>& sub_inits,
        std::vector<float*>& aBls,
        float *betan)
{
    float temp[bigN];
    NPVectorArray etemp(temp,bigN);

    NPMatrix esuper_trans(super_trans,N,N);

    int blocksizes[N];
    int blockstarts[N];

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    vector<NPArray> eaBls;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
        eaBls.push_back(NPArray(aBls[i],T,Nsubs[i]));
    }
    NPArray ebetan(betan,T,bigN);

    ebetan.row(T-1).setOnes();
    float logtot = 0., cmax;
    for (int t=T-2; t>=0; t--) {
        cmax = -1.*numeric_limits<float>::infinity();
        for (int i=0; i<N; i++) {
            cmax = max(cmax, eaBls[i].row(t+1).maxCoeff());
        }

        for (int i=0; i<N; i++) {
            NPSubArray(temp + blockstarts[i],rs[i],Nsubs[i]).rowwise()
                = (eaBls[i].row(t+1) - cmax).exp();
        }
        etemp *= ebetan.row(t+1);

        float tot = just_fast_mult(N,Nsubs,rs,ps,esuper_trans,
                esub_transs,esub_inits,blocksizes,blockstarts,
                temp,betan + bigN*t);
        ebetan.row(t) /= tot;

        logtot += cmax + log(tot);
    }

    // NOTE: all this stuff is necessary to compute the log likelihood including
    // the initial state distribution

    float in_potential[bigN];
    memset(in_potential,0,sizeof(in_potential));
    cmax = -1.*numeric_limits<float>::infinity();
    for (int i=0; i<N; i++) {
        cmax = max(cmax, eaBls[i].row(0).maxCoeff());
    }
    for (int i=0; i<N; i++) {
        NPSubVectorArray(in_potential + blockstarts[i],Nsubs[i]) =
            init_state_distn[i] * esub_inits[i].array() * (eaBls[i].row(0) - cmax).exp().transpose();
    }
    logtot += cmax + log((NPVectorArray(in_potential,bigN) * ebetan.row(0).transpose()).sum());

    return logtot;
}

float subhmm::messages_forwards_normalized(
        int T, int bigN, int N, int32_t *Nsubs,
        int32_t *rs, float *ps, float *super_trans, float *init_state_distn,
        std::vector<float*>& sub_transs, std::vector<float*>& sub_inits,
        std::vector<float*>& aBls,
        float *alphan)
{
    float in_potential[bigN] __attribute__ ((aligned(16)));
    int blocksizes[N];
    int blockstarts[N];
    NPMatrix esuper_trans_T(super_trans,N,N);
    esuper_trans_T.transposeInPlace();

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    vector<NPArray> eaBls;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
        eaBls.push_back(NPArray(aBls[i],T,Nsubs[i]));
    }
    NPArray ealphan(alphan,T,bigN);

    NPVectorArray ein_potential(in_potential,bigN);
    ein_potential.setZero();
    for (int i=0; i<N; i++) {
        ein_potential.segment(blockstarts[i],Nsubs[i]) =
            init_state_distn[i] * esub_inits[i].array();
    }
    float logtot = 0., cmax;
    for (int t=0; t<T; t++) {
        cmax = -1.*numeric_limits<float>::infinity();
        for (int i=0; i<N; i++) {
            cmax = max(cmax, eaBls[i].row(t).maxCoeff());
        }

        for (int i=0; i<N; i++) {
            NPSubArray(in_potential + blockstarts[i],rs[i],Nsubs[i]).rowwise()
                *= (eaBls[i].row(t) - cmax).exp();
        }
        float tot = ein_potential.sum();
        ealphan.row(t) = ein_potential / tot;
        logtot += log(tot) + cmax;

        just_fast_left_mult(N,Nsubs,rs,ps,esuper_trans_T,
                esub_transs,esub_inits,blocksizes,blockstarts,
                alphan + bigN*t,in_potential);
    }
    return logtot;
}

// these next ones are for testing

void subhmm::fast_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        float *super_trans, vector<float*>& sub_transs, vector<float*>& sub_inits,
        float *v, float *out)
{
    // prep work!
    int blocksizes[N];
    int blockstarts[N];
    NPMatrix esuper_trans(super_trans,N,N);

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
    }

    just_fast_mult(N, Nsubs, rs, ps, esuper_trans, esub_transs, esub_inits,
            blocksizes, blockstarts,
            v, out);
}

void subhmm::fast_left_mult(
        int N, int32_t *Nsubs, int32_t *rs, float *ps,
        float *super_trans, vector<float*>& sub_transs, vector<float*>& sub_inits,
        float *v, float *out)
{
    // prep work!
    int blocksizes[N];
    int blockstarts[N];

    float super_trans_T[N*N];
    NPMatrix esuper_trans_T(super_trans_T,N,N);
    esuper_trans_T = NPMatrix(super_trans,N,N).transpose();

    vector<NPMatrix> esub_transs;
    vector<NPVector> esub_inits;
    int totsize = 0;
    for (int i=0; i<N; i++) {
        blockstarts[i] = totsize;
        blocksizes[i] = Nsubs[i]*rs[i];
        totsize += blocksizes[i];

        esub_transs.push_back(NPMatrix(sub_transs[i],Nsubs[i],Nsubs[i]));
        esub_inits.push_back(NPVector(sub_inits[i],Nsubs[i]));
    }

    just_fast_left_mult(N, Nsubs, rs, ps, esuper_trans_T, esub_transs, esub_inits,
            blocksizes, blockstarts,
            v, out);
}

<|endoftext|>


<commit_before>#pragma once

#include "numeric_types.hh"
#include "ll/parse.hh"

struct guid_t {
    uint32_t data1;
    uint16_t data2;
    uint16_t data3;
    uint8_t data4[8];

    constexpr guid_t(const char*);
    constexpr bool operator==(const guid_t&);
};

constexpr guid_t::guid_t(const char* string)
    : data1((hton(string[0]) << 28) + (hton(string[1]) << 24) + (hton(string[2]) << 20) + (hton(string[3]) << 16)
          + (hton(string[4]) << 12) + (hton(string[5]) << 8) + (hton(string[6]) << 4) + (hton(string[7])))
    , data2(static_cast<uint16_t>(
          (hton(string[9]) << 12) + (hton(string[10]) << 8) + (hton(string[11]) << 4) + (hton(string[12]))))
    , data3(static_cast<uint16_t>(
          (hton(string[14]) << 12) + (hton(string[15]) << 8) + (hton(string[16]) << 4) + (hton(string[17]))))
    , data4{ static_cast<uint8_t>((hton(string[19]) << 4) + hton(string[20])),
        static_cast<uint8_t>((hton(string[21]) << 4) + hton(string[22])),
        static_cast<uint8_t>((hton(string[24]) << 4) + hton(string[25])),
        static_cast<uint8_t>((hton(string[26]) << 4) + hton(string[27])),
        static_cast<uint8_t>((hton(string[28]) << 4) + hton(string[29])),
        static_cast<uint8_t>((hton(string[30]) << 4) + hton(string[31])),
        static_cast<uint8_t>((hton(string[32]) << 4) + hton(string[33])),
        static_cast<uint8_t>((hton(string[34]) << 4) + hton(string[35])) }
{
}

constexpr bool guid_t::operator==(const guid_t& that)
{
    return this->data1 == that.data1 && this->data2 == that.data2 && this->data3 == that.data3
        && this->data4[0] == that.data4[0] && this->data4[1] == that.data4[1] && this->data4[2] == that.data4[2]
        && this->data4[3] == that.data4[3] && this->data4[4] == that.data4[4] && this->data4[5] == that.data4[5]
        && this->data4[6] == that.data4[6] && this->data4[7] == that.data4[7];
}

constexpr guid_t operator""_guid(const char* lit, size_t sz) { return guid_t(lit); };

<commit_msg>Typo, d'oh<commit_after>#pragma once

#include "numeric_types.hh"
#include "ll/parse.hh"

struct guid_t {
    uint32_t data1;
    uint16_t data2;
    uint16_t data3;
    uint8_t data4[8];

    constexpr guid_t(const char*);
    constexpr bool operator==(const guid_t&);
};

constexpr guid_t::guid_t(const char* string)
    : data1((ll::Parse::hton(string[0]) << 28) + (ll::Parse::hton(string[1]) << 24) + (ll::Parse::hton(string[2]) << 20) + (ll::Parse::hton(string[3]) << 16)
          + (ll::Parse::hton(string[4]) << 12) + (ll::Parse::hton(string[5]) << 8) + (ll::Parse::hton(string[6]) << 4) + (ll::Parse::hton(string[7])))
    , data2(static_cast<uint16_t>(
          (ll::Parse::hton(string[9]) << 12) + (ll::Parse::hton(string[10]) << 8) + (ll::Parse::hton(string[11]) << 4) + (ll::Parse::hton(string[12]))))
    , data3(static_cast<uint16_t>(
          (ll::Parse::hton(string[14]) << 12) + (ll::Parse::hton(string[15]) << 8) + (ll::Parse::hton(string[16]) << 4) + (ll::Parse::hton(string[17]))))
    , data4{ static_cast<uint8_t>((ll::Parse::hton(string[19]) << 4) + ll::Parse::hton(string[20])),
        static_cast<uint8_t>((ll::Parse::hton(string[21]) << 4) + ll::Parse::hton(string[22])),
        static_cast<uint8_t>((ll::Parse::hton(string[24]) << 4) + ll::Parse::hton(string[25])),
        static_cast<uint8_t>((ll::Parse::hton(string[26]) << 4) + ll::Parse::hton(string[27])),
        static_cast<uint8_t>((ll::Parse::hton(string[28]) << 4) + ll::Parse::hton(string[29])),
        static_cast<uint8_t>((ll::Parse::hton(string[30]) << 4) + ll::Parse::hton(string[31])),
        static_cast<uint8_t>((ll::Parse::hton(string[32]) << 4) + ll::Parse::hton(string[33])),
        static_cast<uint8_t>((ll::Parse::hton(string[34]) << 4) + ll::Parse::hton(string[35])) }
{
}

constexpr bool guid_t::operator==(const guid_t& that)
{
    return this->data1 == that.data1 && this->data2 == that.data2 && this->data3 == that.data3
        && this->data4[0] == that.data4[0] && this->data4[1] == that.data4[1] && this->data4[2] == that.data4[2]
        && this->data4[3] == that.data4[3] && this->data4[4] == that.data4[4] && this->data4[5] == that.data4[5]
        && this->data4[6] == that.data4[6] && this->data4[7] == that.data4[7];
}

constexpr guid_t operator""_guid(const char* lit, size_t sz) { return guid_t(lit); };

<|endoftext|>


<commit_before>#include "xchainer/native_device.h"

#include <cstdint>
#include <cstring>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/dtype.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/scalar.h"

namespace xchainer {

std::shared_ptr<void> NativeDevice::Allocate(size_t bytesize) { return std::make_unique<uint8_t[]>(bytesize); }

void NativeDevice::MemoryCopyFrom(void* dst, const void* src, size_t bytesize, Device& src_device) {
    assert(nullptr != dynamic_cast<NativeDevice*>(&src_device) && "Native device only supports copy between native devices");
    std::memcpy(dst, src, bytesize);
}

void NativeDevice::MemoryCopyTo(void* dst, const void* src, size_t bytesize, Device& dst_device) {
    assert(nullptr != dynamic_cast<NativeDevice*>(&dst_device) && "Native device only supports copy between native devices");
    std::memcpy(dst, src, bytesize);
}

std::shared_ptr<void> NativeDevice::TransferDataFrom(
        Device& src_device, const std::shared_ptr<void>& src_ptr, size_t offset, size_t bytesize) {
    std::shared_ptr<void> dst_ptr = Allocate(bytesize);
    MemoryCopyFrom(dst_ptr.get(), &(static_cast<int8_t*>(src_ptr.get())[offset]), bytesize, src_device);
    return dst_ptr;
}

std::shared_ptr<void> NativeDevice::TransferDataTo(
        Device& dst_device, const std::shared_ptr<void>& src_ptr, size_t offset, size_t bytesize) {
    return dst_device.TransferDataFrom(*this, src_ptr, offset, bytesize);
}

std::shared_ptr<void> NativeDevice::FromBuffer(const std::shared_ptr<void>& src_ptr, size_t bytesize) {
    (void)bytesize;  // unused
    return src_ptr;
}

void NativeDevice::Fill(Array& out, Scalar value) {
    VisitDtype(out.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        T c_value{value};

        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{out.shape()};
        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = c_value;
        }
    });
}

void NativeDevice::Sum(const Array& src, const std::vector<int8_t>& axis, Array& out) {
    Expects(axis.size() == src.shape().size() - out.shape().size());
    CheckDevicesCompatible(src, out);

    VisitDtype(src.dtype(), [&src, &axis, &out](auto pt) {
        using T = typename decltype(pt)::type;
        const Shape& out_shape = out.shape();

        // In the following logic, output dimensions are first iterated over with `out_indexer`,
        // and then reduction dimensions with `reduce_indexer` in nested manner.
        // `src_indexer` is composed from `out_indexer` and `reduce_indexer` to point a single source value.

        // Example:
        // - src.shape():      (2, 3, 4, 5)
        // - axis:             (1, 3)
        // - out.shape():      (2, 4)
        // - reduce_shape_vec: (3, 5)
        // - out_axis:         (0, 2)

        // Prepare dimension mappings
        std::vector<int64_t> reduce_shape_vec;  // Reduction dimensions
        std::vector<int8_t> out_axis;           // Mapping from output indices to src indices
        out_axis.reserve(out.shape().size());
        reduce_shape_vec.reserve(axis.size());
        int8_t i_axis = 0;
        for (int8_t i = 0; i < src.shape().ndim(); ++i) {
            if (i == axis[i_axis]) {
                ++i_axis;
                reduce_shape_vec.push_back(src.shape()[i]);
            } else {
                out_axis.push_back(i);
            }
        }
        Ensures(out_axis.size() == src.shape().size() - axis.size());
        Ensures(reduce_shape_vec.size() == axis.size());

        // Calculate sum
        IndexableArray<const T> src_iarray{src};
        IndexableArray<T> out_iarray{out};
        Indexer<> src_indexer{src.shape()};
        Indexer<> reduce_indexer{Shape{reduce_shape_vec.begin(), reduce_shape_vec.end()}};
        Indexer<> out_indexer{out_shape};

        // Iterate over output dimensions
        for (int64_t i_out = 0; i_out < out_indexer.total_size(); ++i_out) {
            out_indexer.Set(i_out);
            T sum_value = 0;
            gsl::span<int64_t> src_index = gsl::make_span(src_indexer.index(), src.shape().size());

            // Set output indices in the corresponding indices (out_axis) in src_index.
            for (int8_t i_out_dim = 0; i_out_dim < out_indexer.ndim(); ++i_out_dim) {
                src_index[out_axis[i_out_dim]] = out_indexer.index()[i_out_dim];
            }

            // Iterate over reduction dimensions, reducing into a single output value.
            for (int64_t i_reduce = 0; i_reduce < reduce_indexer.total_size(); ++i_reduce) {
                reduce_indexer.Set(i_reduce);
                // Set reduction indices in the corresponding indices (axis) in src_index.
                for (int8_t i_reduce_dim = 0; i_reduce_dim < static_cast<int8_t>(axis.size()); ++i_reduce_dim) {
                    src_index[axis[i_reduce_dim]] = reduce_indexer.index()[i_reduce_dim];
                }

                sum_value += src_iarray[src_indexer];
            }
            out_iarray[out_indexer] = sum_value;
        }
    });
}

void NativeDevice::Copy(const Array& src, Array& out) {
    CheckDevicesCompatible(src, out);
    VisitDtype(src.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> src_iarray{src};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{src.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = src_iarray[indexer];
        }
    });
}

void NativeDevice::Add(const Array& lhs, const Array& rhs, Array& out) {
    CheckDevicesCompatible(lhs, rhs, out);
    VisitDtype(lhs.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> lhs_iarray{lhs};
        IndexableArray<const T> rhs_iarray{rhs};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{lhs.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = lhs_iarray[indexer] + rhs_iarray[indexer];
        }
    });
}

void NativeDevice::Mul(const Array& lhs, const Array& rhs, Array& out) {
    CheckDevicesCompatible(lhs, rhs, out);
    VisitDtype(lhs.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> lhs_iarray{lhs};
        IndexableArray<const T> rhs_iarray{rhs};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{lhs.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = lhs_iarray[indexer] * rhs_iarray[indexer];
        }
    });
}

void NativeDevice::Synchronize() {}

}  // namespace xchainer
<commit_msg>Move example comment for intermediate variables<commit_after>#include "xchainer/native_device.h"

#include <cstdint>
#include <cstring>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/dtype.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/scalar.h"

namespace xchainer {

std::shared_ptr<void> NativeDevice::Allocate(size_t bytesize) { return std::make_unique<uint8_t[]>(bytesize); }

void NativeDevice::MemoryCopyFrom(void* dst, const void* src, size_t bytesize, Device& src_device) {
    assert(nullptr != dynamic_cast<NativeDevice*>(&src_device) && "Native device only supports copy between native devices");
    std::memcpy(dst, src, bytesize);
}

void NativeDevice::MemoryCopyTo(void* dst, const void* src, size_t bytesize, Device& dst_device) {
    assert(nullptr != dynamic_cast<NativeDevice*>(&dst_device) && "Native device only supports copy between native devices");
    std::memcpy(dst, src, bytesize);
}

std::shared_ptr<void> NativeDevice::TransferDataFrom(
        Device& src_device, const std::shared_ptr<void>& src_ptr, size_t offset, size_t bytesize) {
    std::shared_ptr<void> dst_ptr = Allocate(bytesize);
    MemoryCopyFrom(dst_ptr.get(), &(static_cast<int8_t*>(src_ptr.get())[offset]), bytesize, src_device);
    return dst_ptr;
}

std::shared_ptr<void> NativeDevice::TransferDataTo(
        Device& dst_device, const std::shared_ptr<void>& src_ptr, size_t offset, size_t bytesize) {
    return dst_device.TransferDataFrom(*this, src_ptr, offset, bytesize);
}

std::shared_ptr<void> NativeDevice::FromBuffer(const std::shared_ptr<void>& src_ptr, size_t bytesize) {
    (void)bytesize;  // unused
    return src_ptr;
}

void NativeDevice::Fill(Array& out, Scalar value) {
    VisitDtype(out.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        T c_value{value};

        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{out.shape()};
        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = c_value;
        }
    });
}

void NativeDevice::Sum(const Array& src, const std::vector<int8_t>& axis, Array& out) {
    Expects(axis.size() == src.shape().size() - out.shape().size());
    CheckDevicesCompatible(src, out);

    VisitDtype(src.dtype(), [&src, &axis, &out](auto pt) {
        using T = typename decltype(pt)::type;
        const Shape& out_shape = out.shape();

        // In the following logic, output dimensions are first iterated over with `out_indexer`,
        // and then reduction dimensions with `reduce_indexer` in nested manner.
        // `src_indexer` is composed from `out_indexer` and `reduce_indexer` to point a single source value.

        // Prepare dimension mappings
        std::vector<int64_t> reduce_shape_vec;  // Reduction dimensions
        std::vector<int8_t> out_axis;           // Mapping from output indices to src indices
        // Example:
        // - src.shape():      (2, 3, 4, 5)
        // - axis:             (1, 3)
        // - out.shape():      (2, 4)
        // - reduce_shape_vec: (3, 5)
        // - out_axis:         (0, 2)

        out_axis.reserve(out.shape().size());
        reduce_shape_vec.reserve(axis.size());
        int8_t i_axis = 0;
        for (int8_t i = 0; i < src.shape().ndim(); ++i) {
            if (i == axis[i_axis]) {
                ++i_axis;
                reduce_shape_vec.push_back(src.shape()[i]);
            } else {
                out_axis.push_back(i);
            }
        }
        Ensures(out_axis.size() == src.shape().size() - axis.size());
        Ensures(reduce_shape_vec.size() == axis.size());

        // Calculate sum
        IndexableArray<const T> src_iarray{src};
        IndexableArray<T> out_iarray{out};
        Indexer<> src_indexer{src.shape()};
        Indexer<> reduce_indexer{Shape{reduce_shape_vec.begin(), reduce_shape_vec.end()}};
        Indexer<> out_indexer{out_shape};

        // Iterate over output dimensions
        for (int64_t i_out = 0; i_out < out_indexer.total_size(); ++i_out) {
            out_indexer.Set(i_out);
            T sum_value = 0;
            gsl::span<int64_t> src_index = gsl::make_span(src_indexer.index(), src.shape().size());

            // Set output indices in the corresponding indices (out_axis) in src_index.
            for (int8_t i_out_dim = 0; i_out_dim < out_indexer.ndim(); ++i_out_dim) {
                src_index[out_axis[i_out_dim]] = out_indexer.index()[i_out_dim];
            }

            // Iterate over reduction dimensions, reducing into a single output value.
            for (int64_t i_reduce = 0; i_reduce < reduce_indexer.total_size(); ++i_reduce) {
                reduce_indexer.Set(i_reduce);
                // Set reduction indices in the corresponding indices (axis) in src_index.
                for (int8_t i_reduce_dim = 0; i_reduce_dim < static_cast<int8_t>(axis.size()); ++i_reduce_dim) {
                    src_index[axis[i_reduce_dim]] = reduce_indexer.index()[i_reduce_dim];
                }

                sum_value += src_iarray[src_indexer];
            }
            out_iarray[out_indexer] = sum_value;
        }
    });
}

void NativeDevice::Copy(const Array& src, Array& out) {
    CheckDevicesCompatible(src, out);
    VisitDtype(src.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> src_iarray{src};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{src.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = src_iarray[indexer];
        }
    });
}

void NativeDevice::Add(const Array& lhs, const Array& rhs, Array& out) {
    CheckDevicesCompatible(lhs, rhs, out);
    VisitDtype(lhs.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> lhs_iarray{lhs};
        IndexableArray<const T> rhs_iarray{rhs};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{lhs.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = lhs_iarray[indexer] + rhs_iarray[indexer];
        }
    });
}

void NativeDevice::Mul(const Array& lhs, const Array& rhs, Array& out) {
    CheckDevicesCompatible(lhs, rhs, out);
    VisitDtype(lhs.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        IndexableArray<const T> lhs_iarray{lhs};
        IndexableArray<const T> rhs_iarray{rhs};
        IndexableArray<T> out_iarray{out};
        Indexer<> indexer{lhs.shape()};

        for (int64_t i = 0; i < indexer.total_size(); ++i) {
            indexer.Set(i);
            out_iarray[indexer] = lhs_iarray[indexer] * rhs_iarray[indexer];
        }
    });
}

void NativeDevice::Synchronize() {}

}  // namespace xchainer
<|endoftext|>


<commit_before><commit_msg>Sergey's fix for tests<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <test/test_syscoin_services.h>
#include <util/time.h>
#include <rpc/server.h>
#include <services/asset.h>
#include <base58.h>
#include <chainparams.h>
#include <boost/test/unit_test.hpp>
#include <iterator>
#include <key.h>
#include <rpc/util.h>
#include <core_io.h>
using namespace std;
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );
BOOST_FIXTURE_TEST_SUITE(syscoin_asset_allocation_tests, BasicSyscoinTestingSetup)

BOOST_AUTO_TEST_CASE(generate_asset_allocation_address_sync)
{
	UniValue r;
	printf("Running generate_asset_allocation_address_sync...\n");
	GenerateBlocks(5);
	string newaddress = GetNewFundedAddress("node1");
    BOOST_CHECK_NO_THROW(r = CallExtRPC("node1", "getnewaddress"));
    string newaddressreceiver = r.get_str();
	string guid = AssetNew("node1", newaddress, "data", "''", "8", "10000", "1000000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddressreceiver + "\\\",\\\"amount\\\":5000}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");
	StopNode("node2");
	StartNode("node2");
	GenerateBlocks(5, "node2");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");

}
BOOST_AUTO_TEST_CASE(generate_asset_allocation_lock)
{
	UniValue r;
	printf("Running generate_asset_allocation_lock...\n");
	GenerateBlocks(5);
	string txid;
	string newaddress1 = GetNewFundedAddress("node2");
	string newaddress = GetNewFundedAddress("node1", txid);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "getrawtransaction " + txid + " true"));
	UniValue voutArray = find_value(r.get_obj(), "vout");
	int vout = 0;
	CAmount nAmount = 0;
	for (unsigned int i = 0; i<voutArray.size(); i++) {
		nAmount = AmountFromValue(find_value(voutArray[i].get_obj(), "value"));
		UniValue scriptObj = find_value(voutArray[i].get_obj(), "scriptPubKey").get_obj();
		UniValue addressesArray = find_value(scriptObj, "addresses");
		for (unsigned int j = 0; j<addressesArray.size(); j++) {
			if (addressesArray[j].get_str() == newaddress) {
				vout = i;
				nAmount = AmountFromValue(find_value(voutArray[i].get_obj(), "value"));
			}
		}
	}
	// for fees;
	nAmount -= 10000;
	string strAmount = ValueFromAmount(nAmount).write();
	string voutstr = itostr(vout);
	// lock outpoint so other txs can't spend through wallet auto-selection
	BOOST_CHECK_NO_THROW(CallRPC("node1", "lockunspent false \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\""));

	string guid = AssetNew("node1", newaddress, "data", "''", "8", "1", "100000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddress + "\\\",\\\"amount\\\":1}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 1 * COIN);

	LockAssetAllocation("node1", guid, newaddress, txid, voutstr);

	// unlock now to test spending
	BOOST_CHECK_NO_THROW(CallRPC("node1", "lockunspent true \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\""));
	// cannot spend as normal through sendrawtransaction
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "createrawtransaction \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\" \"[{\\\"" + newaddress1 + "\\\":" + strAmount + "}]\"", true, false));

	string rawTx = r.get_str();
	rawTx.erase(std::remove(rawTx.begin(), rawTx.end(), '\n'), rawTx.end());
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "signrawtransactionwithwallet " + rawTx));

	string hex_str = find_value(r.get_obj(), "hex").get_str();
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "testmempoolaccept \"[\\\"" + hex_str + "\\\"]\""));
	BOOST_CHECK(find_value(r.get_array()[0].get_obj(), "allowed").get_bool());
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "sendrawtransaction " + hex_str, true, false));
	BOOST_CHECK(r.write().empty());
	string txid0 = AssetAllocationTransfer(false, "node1", guid, newaddress, "\"[{\\\"address\\\":\\\"" + newaddress1 + "\\\",\\\"amount\\\":0.11}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress1));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.11 * COIN);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "getrawtransaction " + txid0 + " true"));
	UniValue vinArray = find_value(r.get_obj(), "vin");
	bool found = false;
	for (unsigned int i = 0; i<vinArray.size(); i++) {
		if (find_value(vinArray[i].get_obj(), "txid").get_str() == txid && find_value(vinArray[i].get_obj(), "vout").get_int() == vout) {
			found = true;
			break;
		}
	}
	BOOST_CHECK(found);

}
BOOST_AUTO_TEST_CASE(generate_asset_allocation_send_address)
{
	UniValue r;
	printf("Running generate_asset_allocation_send_address...\n");
	GenerateBlocks(5);
    GenerateBlocks(101, "node2");
	string newaddress1 = GetNewFundedAddress("node1");
    CallRPC("node2", "sendtoaddress " + newaddress1 + " 1", true, false);
    CallRPC("node2", "sendtoaddress " + newaddress1 + " 1", true, false);
	GenerateBlocks(5);
	GenerateBlocks(5, "node2");
    BOOST_CHECK_NO_THROW(r = CallExtRPC("node1", "getnewaddress"));
    string newaddress2 = r.get_str();

	string guid = AssetNew("node1", newaddress1, "data","''", "8", "1", "100000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddress1 + "\\\",\\\"amount\\\":1}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress1 ));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 1 * COIN);

	string txid0 = AssetAllocationTransfer(false, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.11}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2 ));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.11 * COIN);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// send using zdag
	string txid1 = AssetAllocationTransfer(true, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.12}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2));
	balance = find_value(r.get_obj(), "balance_zdag");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.23 * COIN);

	// non zdag cannot be found since it was already mined, but ends up briefly in conflict state because sender is conflicted
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// first tx should have to wait 1 sec for good status
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// wait for 1 second as required by unit test
	MilliSleep(1000);
	// second send
	string txid2 = AssetAllocationTransfer(true, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.13}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2 ));
	balance = find_value(r.get_obj(), "balance_zdag");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.36 * COIN);

	// sender is conflicted so txid0 is conflicted by extension even if its not found
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// first ones now OK because it was found explicitly
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// second one hasn't waited enough time yet
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// wait for 1.5 second to clear minor warning status
	MilliSleep(1500);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// after pow, should get not found on all of them
	GenerateBlocks(1);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);
    ECC_Stop();
}
BOOST_AUTO_TEST_SUITE_END ()
<commit_msg>dbg<commit_after>// Copyright (c) 2016-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <test/test_syscoin_services.h>
#include <util/time.h>
#include <rpc/server.h>
#include <services/asset.h>
#include <base58.h>
#include <chainparams.h>
#include <boost/test/unit_test.hpp>
#include <iterator>
#include <key.h>
#include <rpc/util.h>
#include <core_io.h>
using namespace std;
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );
BOOST_FIXTURE_TEST_SUITE(syscoin_asset_allocation_tests, BasicSyscoinTestingSetup)

BOOST_AUTO_TEST_CASE(generate_asset_allocation_address_sync)
{
	UniValue r;
	printf("Running generate_asset_allocation_address_sync...\n");
	GenerateBlocks(5);
	string newaddress = GetNewFundedAddress("node1");
    BOOST_CHECK_NO_THROW(r = CallExtRPC("node1", "getnewaddress"));
    string newaddressreceiver = r.get_str();
	string guid = AssetNew("node1", newaddress, "data", "''", "8", "10000", "1000000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddressreceiver + "\\\",\\\"amount\\\":5000}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");
	StopNode("node2");
	StartNode("node2");
	GenerateBlocks(5, "node2");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid + " " + newaddressreceiver ));
	balance = find_value(r.get_obj(), "balance");

}
BOOST_AUTO_TEST_CASE(generate_asset_allocation_lock)
{
	UniValue r;
	printf("Running generate_asset_allocation_lock...\n");
	GenerateBlocks(5);
	string txid;
	string newaddress1 = GetNewFundedAddress("node2");
	string newaddress = GetNewFundedAddress("node1", txid);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "getrawtransaction " + txid + " true"));
	UniValue voutArray = find_value(r.get_obj(), "vout");
	int vout = 0;
	CAmount nAmount = 0;
	for (unsigned int i = 0; i<voutArray.size(); i++) {
		nAmount = AmountFromValue(find_value(voutArray[i].get_obj(), "value"));
		UniValue scriptObj = find_value(voutArray[i].get_obj(), "scriptPubKey").get_obj();
		UniValue addressesArray = find_value(scriptObj, "addresses");
		for (unsigned int j = 0; j<addressesArray.size(); j++) {
			if (addressesArray[j].get_str() == newaddress) {
				vout = i;
				nAmount = AmountFromValue(find_value(voutArray[i].get_obj(), "value"));
			}
		}
	}
	// for fees;
	nAmount -= 10000;
	string strAmount = ValueFromAmount(nAmount).write();
	string voutstr = itostr(vout);
	// lock outpoint so other txs can't spend through wallet auto-selection
	BOOST_CHECK_NO_THROW(CallRPC("node1", "lockunspent false \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\""));

	string guid = AssetNew("node1", newaddress, "data", "''", "8", "1", "100000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddress + "\\\",\\\"amount\\\":1}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 1 * COIN);

	LockAssetAllocation("node1", guid, newaddress, txid, voutstr);

	// unlock now to test spending
	BOOST_CHECK_NO_THROW(CallRPC("node1", "lockunspent true \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\""));
	// cannot spend as normal through sendrawtransaction
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "createrawtransaction \"[{\\\"txid\\\":\\\"" + txid + "\\\",\\\"vout\\\":" + voutstr + "}]\" \"[{\\\"" + newaddress1 + "\\\":" + strAmount + "}]\"", true, false));

	string rawTx = r.get_str();
	rawTx.erase(std::remove(rawTx.begin(), rawTx.end(), '\n'), rawTx.end());
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "signrawtransactionwithwallet " + rawTx));

	string hex_str = find_value(r.get_obj(), "hex").get_str();
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "testmempoolaccept \"[\\\"" + hex_str + "\\\"]\""));
	BOOST_CHECK(find_value(r.get_array()[0].get_obj(), "allowed").get_bool());
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "sendrawtransaction " + hex_str, true, false));
	printf("%s\n", r.write().c_str());
	BOOST_CHECK(r.write().empty());
	string txid0 = AssetAllocationTransfer(false, "node1", guid, newaddress, "\"[{\\\"address\\\":\\\"" + newaddress1 + "\\\",\\\"amount\\\":0.11}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress1));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.11 * COIN);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "getrawtransaction " + txid0 + " true"));
	UniValue vinArray = find_value(r.get_obj(), "vin");
	bool found = false;
	for (unsigned int i = 0; i<vinArray.size(); i++) {
		if (find_value(vinArray[i].get_obj(), "txid").get_str() == txid && find_value(vinArray[i].get_obj(), "vout").get_int() == vout) {
			found = true;
			break;
		}
	}
	BOOST_CHECK(found);

}
BOOST_AUTO_TEST_CASE(generate_asset_allocation_send_address)
{
	UniValue r;
	printf("Running generate_asset_allocation_send_address...\n");
	GenerateBlocks(5);
    GenerateBlocks(101, "node2");
	string newaddress1 = GetNewFundedAddress("node1");
    CallRPC("node2", "sendtoaddress " + newaddress1 + " 1", true, false);
    CallRPC("node2", "sendtoaddress " + newaddress1 + " 1", true, false);
	GenerateBlocks(5);
	GenerateBlocks(5, "node2");
    BOOST_CHECK_NO_THROW(r = CallExtRPC("node1", "getnewaddress"));
    string newaddress2 = r.get_str();

	string guid = AssetNew("node1", newaddress1, "data","''", "8", "1", "100000");

	AssetSend("node1", guid, "\"[{\\\"address\\\":\\\"" + newaddress1 + "\\\",\\\"amount\\\":1}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress1 ));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 1 * COIN);

	string txid0 = AssetAllocationTransfer(false, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.11}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2 ));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.11 * COIN);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// send using zdag
	string txid1 = AssetAllocationTransfer(true, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.12}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2));
	balance = find_value(r.get_obj(), "balance_zdag");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.23 * COIN);

	// non zdag cannot be found since it was already mined, but ends up briefly in conflict state because sender is conflicted
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// first tx should have to wait 1 sec for good status
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// wait for 1 second as required by unit test
	MilliSleep(1000);
	// second send
	string txid2 = AssetAllocationTransfer(true, "node1", guid, newaddress1, "\"[{\\\"address\\\":\\\"" + newaddress2 + "\\\",\\\"amount\\\":0.13}]\"");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " " + newaddress2 ));
	balance = find_value(r.get_obj(), "balance_zdag");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8), 0.36 * COIN);

	// sender is conflicted so txid0 is conflicted by extension even if its not found
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// first ones now OK because it was found explicitly
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// second one hasn't waited enough time yet
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT);

	// wait for 1.5 second to clear minor warning status
	MilliSleep(1500);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// after pow, should get not found on all of them
	GenerateBlocks(1);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " " + newaddress1 + " ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);
    ECC_Stop();
}
BOOST_AUTO_TEST_SUITE_END ()
<|endoftext|>


<commit_before>#include <cctag/visualDebug.hpp>
#include <cctag/fileDebug.hpp>

#include <boost/filesystem.hpp>
#include <opencv2/opencv.hpp>

namespace bfs = boost::filesystem;

namespace cctag
{

CCTagVisualDebug::CCTagVisualDebug()
{
}

CCTagVisualDebug::~CCTagVisualDebug()
{
}

void CCTagVisualDebug::initializeFolders(const boost::filesystem::path & rootPath, const std::string & outputFolder, std::size_t nCrowns)
{
#ifdef CCTAG_SERIALIZE
  // Create inputImagePath/result if it does not exist
  std::stringstream resultFolderName, localizationFolderName, identificationFolderName, absoluteOutputFolderName;

  resultFolderName << rootPath.string();

  if( outputFolder != "" ) {
    resultFolderName << "/" << outputFolder;
    if (!bfs::exists(resultFolderName.str())) {
      bfs::create_directory(resultFolderName.str());
    }
  }

  resultFolderName << "/cctag" << nCrowns << "CC";

  if (!bfs::exists(resultFolderName.str())) {
      bfs::create_directory(resultFolderName.str());
  }

  localizationFolderName << resultFolderName.str() << "/localization";
  identificationFolderName << resultFolderName.str() << "/identification";

  if (!bfs::exists(localizationFolderName.str())) {
      bfs::create_directory(localizationFolderName.str());
  }

  if (!bfs::exists(identificationFolderName.str())) {
      bfs::create_directory(identificationFolderName.str());
  }

  _pathRoot = resultFolderName.str();
  CCTAG_COUT_VAR(_pathRoot);
#endif
}

void CCTagVisualDebug::setPyramidLevel(int level) {
#ifdef CCTAG_SERIALIZE
  _pyramidLevel = level;
#endif
}

int CCTagVisualDebug::getPyramidLevel() {
    return _pyramidLevel;
}

std::string CCTagVisualDebug::getPath() const {
  return _path;
}

void CCTagVisualDebug::setImageFileName(const std::string& imageFileName) {
#ifdef CCTAG_SERIALIZE
  _imageFileName = imageFileName;
    CCTAG_COUT_VAR(_imageFileName);
  _path = _pathRoot + "/" + imageFileName;
  CCTAG_COUT_VAR(_path);
  if (!bfs::exists(_path)) {
    bfs::create_directory(_path);
    CCTAG_COUT("creation done");
  }
  CCTAG_COUT("exit");
#endif
}

void CCTagVisualDebug::initBackgroundImage(const cv::Mat & back)
{
#ifdef CCTAG_SERIALIZE
  cv::Mat temp; // todo@Lilian: why do I need to use temp ?
  cvtColor(back, temp, cv::COLOR_GRAY2RGB);
  _backImage = temp.clone();
#endif
}

void CCTagVisualDebug::newSession(const std::string & sessionName) {
#ifdef CCTAG_SERIALIZE
  // Don't erase old sessions
  if (_sessions.find(sessionName) == _sessions.end()) {
      _sessions[sessionName] = _backImage;
  }
#endif
}

void CCTagVisualDebug::drawText(const cctag::Point2dN<double> & p, const std::string & text, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  CvFont font1;
  cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.8, 0.8, 0, 2);

  IplImage iplBack = _backImage;
  cvPutText( &iplBack, text.c_str(),
          cvPoint((int) p.x(), (int) p.y()),
          &font1, CV_RGB(color[0] * 255, color[1] * 255, color[2] * 255));
#endif
}

void CCTagVisualDebug::drawPoint(const cctag::Point2dN<double> & point, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  if (point.x() >= 1 && point.x() < _backImage.cols-1 &&
          point.y() >= 1 && point.y() < _backImage.rows-1)
  {
    cv::Vec3b cvColor;
    cvColor.val[0] = 255*color[0];
    cvColor.val[1] = 255*color[1];
    cvColor.val[2] = 255*color[2];
    _backImage.at<cv::Vec3b>(point.y(),point.x()) = cvColor;
    //cv::rectangle(_backImage, cvPoint(point.x()-1.0,point.y()-1.0), cvPoint(point.x()+1.0,point.y()+1.0), cv::Scalar(255*color[0], 255*color[1], 255*color[2]),0);
  }
#endif // CCTAG_SERIALIZE
}

void CCTagVisualDebug::drawPoint(const cctag::DirectedPoint2d<double> & point, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  if (point.x() >= 1 && point.x() < _backImage.cols-1 &&
          point.y() >= 1 && point.y() < _backImage.rows-1)
  {
    //cv::Vec3b cvColor;
    //cvColor.val[0] = 255*color[0];
    //cvColor.val[1] = 255*color[1];
    //cvColor.val[2] = 255*color[2];
    //_backImage.at<cv::Vec3b>(point.y(),point.x()) = cvColor;
    cv::Point p1(point.x(),point.y());
    cv::Point p2(point.x() + point.dX(),point.y() + point.dY());
    cv::arrowedLine( _backImage, p1, p2, cv::Scalar(255*color[0], 255*color[1], 255*color[2]) );

    //cv::rectangle(_backImage, cvPoint(point.x()-1.0,point.y()-1.0), cvPoint(point.x()+1.0,point.y()+1.0), cv::Scalar(255*color[0], 255*color[1], 255*color[2]),0);
  }
#endif // CCTAG_SERIALIZE
}

void CCTagVisualDebug::drawPoints(const std::vector<cctag::Point2dN<double> > & points, const cctag::Color & color)
{
#ifdef CCTAG_SERIALIZE
  BOOST_FOREACH(const cctag::Point2dN<double> & point, points) {
      CCTagVisualDebug::instance().drawPoint(point, cctag::color_red);
  }
#endif
}

// todo templater la function ci-dessus avec celle ci-dessous
void CCTagVisualDebug::drawPoints(const std::vector<cctag::DirectedPoint2d<double> > & points, const cctag::Color & color)
{
#ifdef CCTAG_SERIALIZE
  BOOST_FOREACH(const cctag::Point2dN<double> & point, points) {
      CCTagVisualDebug::instance().drawPoint(cctag::Point2dN<double>(point.x(),point.y()), cctag::color_red);
  }
#endif
}

void CCTagVisualDebug::drawMarker(const cctag::CCTag& marker, bool drawScaledMarker)
{
#ifdef CCTAG_SERIALIZE
  numerical::geometry::Ellipse rescaledOuterEllipse;
  if (drawScaledMarker) {
      rescaledOuterEllipse = marker.rescaledOuterEllipse();
  } else {
      rescaledOuterEllipse = marker.outerEllipse();
  }
  Point2dN<double> & center = rescaledOuterEllipse.center();

  // Display ellipses
  if (drawScaledMarker) {
      rescaledOuterEllipse = marker.rescaledOuterEllipse();
  } else {
      rescaledOuterEllipse = marker.outerEllipse();
  }

  cv::Scalar color;
  // Set the color
  if (marker.getStatus() == status::no_collected_cuts) {
    // Magenta
    color = cv::Scalar(255,0,255);
  }else if (marker.getStatus() == status::no_selected_cuts) {
    // Cyan
    color = cv::Scalar(0,255,255);
  }else if(marker.getStatus() == status::opti_has_diverged){
    // Red
    color = cv::Scalar(255,0,0);
  }else if(marker.getStatus() == status::id_not_reliable){
    // Cyan
    color = cv::Scalar(0,255,255);
  }else if(marker.getStatus() == status::id_reliable){
    // Green
    color = cv::Scalar(0,255,0);
  }else if(marker.getStatus() == status::degenerate){
    // Yellow 1
    color = cv::Scalar(255,255,0);
  }else if(marker.getStatus() == 0 ){
    // Green
    color = cv::Scalar(0,255,0);
  }

  //CCTAT_COUT_VAR(color);

  cv::ellipse(_backImage , cv::Point(center.x(),center.y()),
      cv::Size(rescaledOuterEllipse.a(), rescaledOuterEllipse.b()),
      rescaledOuterEllipse.angle()*180/M_PI, 0, 360, color);
#endif
}

void CCTagVisualDebug::drawInfos(const cctag::CCTag& marker, bool drawScaledMarker)
{
#ifdef CCTAG_SERIALIZE
    CvFont font1;
  cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.8, 0.8, 0, 2);

  std::string sId = boost::lexical_cast<std::string>(marker.id() + 1);

  int x, y;
  if (drawScaledMarker) {
      x = int (marker.rescaledOuterEllipse().center().x());
      y = int (marker.rescaledOuterEllipse().center().y());
  } else {
      x = int (marker.outerEllipse().center().x());
      y = int (marker.outerEllipse().center().y());
  }

  IplImage iplImg = _backImage;
  cvPutText( &iplImg, sId.c_str(),
          cvPoint(x-10, y+10),
          &font1, CV_RGB(255, 140, 0));
#endif
}

std::string CCTagVisualDebug::getImageFileName() const {
    return _imageFileName;
}

void CCTagVisualDebug::out(const std::string & filename) const {
#ifdef CCTAG_SERIALIZE
  cv::imwrite(filename, _backImage);
#endif
}

void CCTagVisualDebug::outPutAllSessions() const {
#ifdef CCTAG_SERIALIZE
    BOOST_FOREACH(const Sessions::const_iterator::value_type & v, _sessions) {
        const std::string filename = _path + "/" + v.first + ".png";
        cv::imwrite(filename, v.second);
    }
#endif
}

void CCTagVisualDebug::writeLocalizationView(cctag::CCTag::List& markers) const {
#ifdef CCTAG_SERIALIZE
    std::stringstream localizationResultFileName;
    localizationResultFileName << "../localization/" << _imageFileName;
    CCTagVisualDebug::instance().newSession(localizationResultFileName.str());

    BOOST_FOREACH(const cctag::CCTag & marker, markers) {
        CCTagVisualDebug::instance().drawMarker(marker);
        CCTagVisualDebug::instance().drawInfos(marker);
    }
#endif
}

void CCTagVisualDebug::writeIdentificationView(cctag::CCTag::List& markers) const {
#ifdef CCTAG_SERIALIZE

    std::stringstream identificationResultFileName;
    identificationResultFileName << "../identification/" << _imageFileName;
    CCTagVisualDebug::instance().newSession(identificationResultFileName.str());

    BOOST_FOREACH(const cctag::CCTag & marker, markers) {
        CCTagVisualDebug::instance().drawMarker(marker);
        CCTagVisualDebug::instance().drawPoints(marker.rescaledOuterEllipsePoints(), cctag::color_red);
        CCTagVisualDebug::instance().drawInfos(marker);
    }

#endif
}

void CCTagVisualDebug::clearSessions() {
#ifdef CCTAG_SERIALIZE
    _sessions.erase(_sessions.begin(), _sessions.end());
#endif
}

} // namespace cctag
<commit_msg>[visualDebug] Allow to enable/disable all the writing of the debug images.<commit_after>#include <cctag/visualDebug.hpp>
#include <cctag/fileDebug.hpp>

#include <boost/filesystem.hpp>
#include <opencv2/opencv.hpp>

namespace bfs = boost::filesystem;

namespace cctag
{

CCTagVisualDebug::CCTagVisualDebug()
{
}

CCTagVisualDebug::~CCTagVisualDebug()
{
}

void CCTagVisualDebug::initializeFolders(const boost::filesystem::path & rootPath, const std::string & outputFolder, std::size_t nCrowns)
{
#ifdef CCTAG_SERIALIZE
  // Create inputImagePath/result if it does not exist
  std::stringstream resultFolderName, localizationFolderName, identificationFolderName, absoluteOutputFolderName;

  resultFolderName << rootPath.string();

  if( outputFolder != "" ) {
    resultFolderName << "/" << outputFolder;
    if (!bfs::exists(resultFolderName.str())) {
      bfs::create_directory(resultFolderName.str());
    }
  }

  resultFolderName << "/cctag" << nCrowns << "CC";

  if (!bfs::exists(resultFolderName.str())) {
      bfs::create_directory(resultFolderName.str());
  }

  localizationFolderName << resultFolderName.str() << "/localization";
  identificationFolderName << resultFolderName.str() << "/identification";

  if (!bfs::exists(localizationFolderName.str())) {
      bfs::create_directory(localizationFolderName.str());
  }

  if (!bfs::exists(identificationFolderName.str())) {
      bfs::create_directory(identificationFolderName.str());
  }

  _pathRoot = resultFolderName.str();
  CCTAG_COUT_VAR(_pathRoot);
#endif
}

void CCTagVisualDebug::setPyramidLevel(int level) {
#ifdef CCTAG_SERIALIZE
  _pyramidLevel = level;
#endif
}

int CCTagVisualDebug::getPyramidLevel() {
    return _pyramidLevel;
}

std::string CCTagVisualDebug::getPath() const {
  return _path;
}

void CCTagVisualDebug::setImageFileName(const std::string& imageFileName) {
#ifdef CCTAG_SERIALIZE
  _imageFileName = imageFileName;
    CCTAG_COUT_VAR(_imageFileName);
  _path = _pathRoot + "/" + imageFileName;
  CCTAG_COUT_VAR(_path);
  if (!bfs::exists(_path)) {
    bfs::create_directory(_path);
    CCTAG_COUT("creation done");
  }
  CCTAG_COUT("exit");
#endif
}

void CCTagVisualDebug::initBackgroundImage(const cv::Mat & back)
{
#ifdef CCTAG_SERIALIZE
  cv::Mat temp; // todo@Lilian: why do I need to use temp ?
  cvtColor(back, temp, cv::COLOR_GRAY2RGB);
  _backImage = temp.clone();
#endif
}

void CCTagVisualDebug::newSession(const std::string & sessionName) {
#ifdef CCTAG_SERIALIZE
  // Don't erase old sessions
  if (_sessions.find(sessionName) == _sessions.end()) {
      _sessions[sessionName] = _backImage;
  }
#endif
}

void CCTagVisualDebug::drawText(const cctag::Point2dN<double> & p, const std::string & text, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  CvFont font1;
  cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.8, 0.8, 0, 2);

  IplImage iplBack = _backImage;
  cvPutText( &iplBack, text.c_str(),
          cvPoint((int) p.x(), (int) p.y()),
          &font1, CV_RGB(color[0] * 255, color[1] * 255, color[2] * 255));
#endif
}

void CCTagVisualDebug::drawPoint(const cctag::Point2dN<double> & point, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  if (point.x() >= 1 && point.x() < _backImage.cols-1 &&
          point.y() >= 1 && point.y() < _backImage.rows-1)
  {
    cv::Vec3b cvColor;
    cvColor.val[0] = 255*color[0];
    cvColor.val[1] = 255*color[1];
    cvColor.val[2] = 255*color[2];
    _backImage.at<cv::Vec3b>(point.y(),point.x()) = cvColor;
    //cv::rectangle(_backImage, cvPoint(point.x()-1.0,point.y()-1.0), cvPoint(point.x()+1.0,point.y()+1.0), cv::Scalar(255*color[0], 255*color[1], 255*color[2]),0);
  }
#endif // CCTAG_SERIALIZE
}

void CCTagVisualDebug::drawPoint(const cctag::DirectedPoint2d<double> & point, const cctag::Color & color) {
#ifdef CCTAG_SERIALIZE
  if (point.x() >= 1 && point.x() < _backImage.cols-1 &&
          point.y() >= 1 && point.y() < _backImage.rows-1)
  {
    //cv::Vec3b cvColor;
    //cvColor.val[0] = 255*color[0];
    //cvColor.val[1] = 255*color[1];
    //cvColor.val[2] = 255*color[2];
    //_backImage.at<cv::Vec3b>(point.y(),point.x()) = cvColor;
    cv::Point p1(point.x(),point.y());
    cv::Point p2(point.x() + point.dX(),point.y() + point.dY());
    cv::arrowedLine( _backImage, p1, p2, cv::Scalar(255*color[0], 255*color[1], 255*color[2]) );

    //cv::rectangle(_backImage, cvPoint(point.x()-1.0,point.y()-1.0), cvPoint(point.x()+1.0,point.y()+1.0), cv::Scalar(255*color[0], 255*color[1], 255*color[2]),0);
  }
#endif // CCTAG_SERIALIZE
}

void CCTagVisualDebug::drawPoints(const std::vector<cctag::Point2dN<double> > & points, const cctag::Color & color)
{
#ifdef CCTAG_SERIALIZE
  BOOST_FOREACH(const cctag::Point2dN<double> & point, points) {
      CCTagVisualDebug::instance().drawPoint(point, cctag::color_red);
  }
#endif
}

// todo templater la function ci-dessus avec celle ci-dessous
void CCTagVisualDebug::drawPoints(const std::vector<cctag::DirectedPoint2d<double> > & points, const cctag::Color & color)
{
#ifdef CCTAG_SERIALIZE
  BOOST_FOREACH(const cctag::Point2dN<double> & point, points) {
      CCTagVisualDebug::instance().drawPoint(cctag::Point2dN<double>(point.x(),point.y()), cctag::color_red);
  }
#endif
}

void CCTagVisualDebug::drawMarker(const cctag::CCTag& marker, bool drawScaledMarker)
{
#ifdef CCTAG_SERIALIZE
  numerical::geometry::Ellipse rescaledOuterEllipse;
  if (drawScaledMarker) {
      rescaledOuterEllipse = marker.rescaledOuterEllipse();
  } else {
      rescaledOuterEllipse = marker.outerEllipse();
  }
  Point2dN<double> & center = rescaledOuterEllipse.center();

  // Display ellipses
  if (drawScaledMarker) {
      rescaledOuterEllipse = marker.rescaledOuterEllipse();
  } else {
      rescaledOuterEllipse = marker.outerEllipse();
  }

  cv::Scalar color;
  // Set the color
  if (marker.getStatus() == status::no_collected_cuts) {
    // Magenta
    color = cv::Scalar(255,0,255);
  }else if (marker.getStatus() == status::no_selected_cuts) {
    // Cyan
    color = cv::Scalar(0,255,255);
  }else if(marker.getStatus() == status::opti_has_diverged){
    // Red
    color = cv::Scalar(255,0,0);
  }else if(marker.getStatus() == status::id_not_reliable){
    // Cyan
    color = cv::Scalar(0,255,255);
  }else if(marker.getStatus() == status::id_reliable){
    // Green
    color = cv::Scalar(0,255,0);
  }else if(marker.getStatus() == status::degenerate){
    // Yellow 1
    color = cv::Scalar(255,255,0);
  }else if(marker.getStatus() == 0 ){
    // Green
    color = cv::Scalar(0,255,0);
  }

  //CCTAT_COUT_VAR(color);

  cv::ellipse(_backImage , cv::Point(center.x(),center.y()),
      cv::Size(rescaledOuterEllipse.a(), rescaledOuterEllipse.b()),
      rescaledOuterEllipse.angle()*180/M_PI, 0, 360, color);
#endif
}

void CCTagVisualDebug::drawInfos(const cctag::CCTag& marker, bool drawScaledMarker)
{
#ifdef CCTAG_SERIALIZE
    CvFont font1;
  cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.8, 0.8, 0, 2);

  std::string sId = boost::lexical_cast<std::string>(marker.id() + 1);

  int x, y;
  if (drawScaledMarker) {
      x = int (marker.rescaledOuterEllipse().center().x());
      y = int (marker.rescaledOuterEllipse().center().y());
  } else {
      x = int (marker.outerEllipse().center().x());
      y = int (marker.outerEllipse().center().y());
  }

  IplImage iplImg = _backImage;
  cvPutText( &iplImg, sId.c_str(),
          cvPoint(x-10, y+10),
          &font1, CV_RGB(255, 140, 0));
#endif
}

std::string CCTagVisualDebug::getImageFileName() const {
    return _imageFileName;
}

void CCTagVisualDebug::out(const std::string & filename) const {
#if defined CCTAG_SERIALIZE && defined VISUAL_DEBUG
  cv::imwrite(filename, _backImage);
#endif
}

void CCTagVisualDebug::outPutAllSessions() const {
#if defined CCTAG_SERIALIZE && defined VISUAL_DEBUG
    BOOST_FOREACH(const Sessions::const_iterator::value_type & v, _sessions) {
        const std::string filename = _path + "/" + v.first + ".png";
        cv::imwrite(filename, v.second);
    }
#endif
}

void CCTagVisualDebug::writeLocalizationView(cctag::CCTag::List& markers) const {
#ifdef CCTAG_SERIALIZE
    std::stringstream localizationResultFileName;
    localizationResultFileName << "../localization/" << _imageFileName;
    CCTagVisualDebug::instance().newSession(localizationResultFileName.str());

    BOOST_FOREACH(const cctag::CCTag & marker, markers) {
        CCTagVisualDebug::instance().drawMarker(marker);
        CCTagVisualDebug::instance().drawInfos(marker);
    }
#endif
}

void CCTagVisualDebug::writeIdentificationView(cctag::CCTag::List& markers) const {
#ifdef CCTAG_SERIALIZE

    std::stringstream identificationResultFileName;
    identificationResultFileName << "../identification/" << _imageFileName;
    CCTagVisualDebug::instance().newSession(identificationResultFileName.str());

    BOOST_FOREACH(const cctag::CCTag & marker, markers) {
        CCTagVisualDebug::instance().drawMarker(marker);
        CCTagVisualDebug::instance().drawPoints(marker.rescaledOuterEllipsePoints(), cctag::color_red);
        CCTagVisualDebug::instance().drawInfos(marker);
    }

#endif
}

void CCTagVisualDebug::clearSessions() {
#ifdef CCTAG_SERIALIZE
    _sessions.erase(_sessions.begin(), _sessions.end());
#endif
}

} // namespace cctag
<|endoftext|>


<commit_before>/**
 * @file Cosa/TWI/Driver/DS1307.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_TWI_DRIVER_DS1307_HH__
#define __COSA_TWI_DRIVER_DS1307_HH__

#include "Cosa/TWI.hh"
#include "Cosa/IOStream.hh"
#include "Cosa/Time.hh"

/**
 * Driver for the DS1307, 64 X 8, Serial I2C Real-Time Clock.
 * For further details see Maxim Integrated product description;
 * http://datasheets.maximintegrated.com/en/ds/DS1307.pdf
 */
class DS1307 : private TWI::Driver {
private:
  static const uint8_t ADDR = 0xD0;

public:
  /**
   * The Timekeeper Registers (Table 2, pp. 8)
   */
  struct timekeeper_t {
    time_t clock;
    union {
      uint8_t as_uint8;
      struct {
	uint8_t rs:2;		// Rate Select
	uint8_t reserved1:2;	// Reserved/1
	uint8_t sqwe:1;		// Square-Ware Enable
	uint8_t reserved2:2;	// Reserved/2
	uint8_t out:1;		// Output Control
      };
    } control;
  };
  const static uint8_t RAM_ADDR = sizeof(timekeeper_t);
  const static uint8_t RAM_MAX = 0x40;

  /**
   * Read ram block with the given size into the buffer from the position.
   * Return number of bytes read or negative error code.
   * @param[in] ram buffer to read from ram.
   * @param[in] size number of bytes to read.
   * @param[in] pos address in ram to read from.
   * @return number of bytes or negative error code.
   */
  int read(void* ram, uint8_t size, uint8_t pos = 0);

  /**
   * Write ram block at given position with the contents from buffer.
   * Return number of bytes written or negative error code.
   * @param[in] buf buffer to write to ram.
   * @param[in] size number of bytes to write.
   * @param[in] pos address in ram to read write to.
   * @return number of bytes or negative error code.
   */
  int write(void* ram, uint8_t size, uint8_t pos = 0);

  /**
   * Read current time from real-time clock. Return true(1)
   * if successful otherwise false(0).
   * @param[out] now time structure return value.
   * @return boolean.
   */
  bool get_time(time_t& now)
  {
    return (read(&now, sizeof(now)) == sizeof(now));
  }

  /**
   * Set the current time from real-time clock with the given
   * time. Return true(1) if successful otherwise false(0).
   * @param[in] now time structure to set.
   * @return boolean.
   */
  bool set_time(time_t& now)
  {
    return (write(&now, sizeof(now)) == sizeof(now));
  }
};

#endif
<commit_msg>Improving DS1307 RTC device driver; refactoring control register access.<commit_after>/**
 * @file Cosa/TWI/Driver/DS1307.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2013, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef __COSA_TWI_DRIVER_DS1307_HH__
#define __COSA_TWI_DRIVER_DS1307_HH__

#include "Cosa/TWI.hh"
#include "Cosa/IOStream.hh"
#include "Cosa/Time.hh"

/**
 * Driver for the DS1307, 64 X 8, Serial I2C Real-Time Clock.
 * For further details see Maxim Integrated product description;
 * http://datasheets.maximintegrated.com/en/ds/DS1307.pdf
 */
class DS1307 : private TWI::Driver {
private:
  static const uint8_t ADDR = 0xD0;

public:
  /**
   * The Timekeeper Control Register (pp. 9)
   */
  union control_t {
    uint8_t as_uint8;
    struct {
      uint8_t rs:2;		// Rate Select
      uint8_t reserved1:2;	// Reserved/1
      uint8_t sqwe:1;		// Square-Ware Enable
      uint8_t reserved2:2;	// Reserved/2
      uint8_t out:1;		// Output Control
    };
  };

  // Rate Selection (pp. 9)
  enum {
    RS_1_HZ,
    RS_4_096_KHZ,
    RS_8_192_KHZ,
    RS_32_768_KHZ
  } __attribute__((packed));

  /**
   * The Timekeeper Registers (Table 2, pp. 8)
   */
  struct timekeeper_t {
    time_t clock;
    control_t control;
  };
  const static uint8_t RAM_ADDR = sizeof(timekeeper_t);
  const static uint8_t RAM_MAX = 0x40;

  /**
   * Read ram block with the given size into the buffer from the position.
   * Return number of bytes read or negative error code.
   * @param[in] ram buffer to read from ram.
   * @param[in] size number of bytes to read.
   * @param[in] pos address in ram to read from.
   * @return number of bytes or negative error code.
   */
  int read(void* ram, uint8_t size, uint8_t pos = 0);

  /**
   * Write ram block at given position with the contents from buffer.
   * Return number of bytes written or negative error code.
   * @param[in] buf buffer to write to ram.
   * @param[in] size number of bytes to write.
   * @param[in] pos address in ram to read write to.
   * @return number of bytes or negative error code.
   */
  int write(void* ram, uint8_t size, uint8_t pos = 0);

  /**
   * Read current time from real-time clock. Return true(1)
   * if successful otherwise false(0).
   * @param[out] now time structure return value.
   * @return boolean.
   */
  bool get_time(time_t& now)
  {
    return (read(&now, sizeof(now)) == sizeof(now));
  }

  /**
   * Set the current time from real-time clock with the given
   * time. Return true(1) if successful otherwise false(0).
   * @param[in] now time structure to set.
   * @return boolean.
   */
  bool set_time(time_t& now)
  {
    return (write(&now, sizeof(now)) == sizeof(now));
  }
};

#endif
<|endoftext|>


<commit_before>// Copyright 2013-2015 Stanford University
//
// 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 "src/cfg/cfg_transforms.h"

using namespace x64asm;

namespace stoke {

void CfgTransforms::remove_unreachable(Cfg& cfg) {
  Code temp;
  for (auto b = cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
    for (auto i = cfg.instr_begin(*b), ie = cfg.instr_end(*b); i != ie; ++i) {
      temp.push_back(*i);
    }
  }

  cfg.get_code() = temp;
  cfg.recompute();
}

void CfgTransforms::remove_nop(Cfg& cfg) {
  Code temp;
  for (auto b = cfg.get_entry(), be = cfg.get_exit(); b != be; ++b) {
    for (auto i = cfg.instr_begin(b), ie = cfg.instr_end(b); i != ie; ++i) {
      if (!i->is_nop()) {
        temp.push_back(*i);
      }
    }
  }

  cfg.get_code() = temp;
  cfg.recompute();
}

/** Returns true if the instruction has any visible side-effect other than
control flow or effect on registers (e.g. memory writes, possibility of
signals, etc.). */
bool has_side_effect(x64asm::Instruction& instr) {
  return instr.is_memory_dereference() ||
    (instr.get_opcode() >= DIV_M16 && instr.get_opcode() <= DIVSS_XMM_XMM);
}

void CfgTransforms::remove_redundant(Cfg& cfg) {
  bool changed = true;
  while (changed) {
    // loop will terminate, as we remove at least one instruction in every iteration, except maybe the last one
    changed = false;
    Code temp;
    for (stoke::Cfg::reachable_iterator b = cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
      size_t c = 0;
      for (auto i = cfg.instr_begin(*b), ie = cfg.instr_end(*b); i != ie; ++i, ++c) {
        bool keep = true;
        if ((*i).is_label_defn() || (*i).is_any_jump() ||
            (*i).is_any_call() || (*i).is_any_return() ||
            (*i).is_any_loop()) {
          // we always keep control flow
        } else if (has_side_effect(*i)) {
          // we always keep instructions that have any side-effect other than
          // on the registers (hardware exceptions, memory writes, etc.)
        } else {
          auto instr_outputs = cfg.maybe_write_set(*i);
          auto live_regs_after_instruction = cfg.live_outs({*b, c});
          if ((instr_outputs & live_regs_after_instruction) == x64asm::RegSet::empty()) {
            // don't keep the instruction if it doesn't produce any values which
            // are live right after that instruction
            keep = false;
          }
        }

        if (keep) {
          temp.push_back(*i);
        } else {
          changed = true; // we removed an instruction
        }
      }
    }

    cfg.get_code() = temp;
    cfg.recompute();
  }
}

} // namespace stoke
<commit_msg>whitespace<commit_after>// Copyright 2013-2015 Stanford University
//
// 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 "src/cfg/cfg_transforms.h"

using namespace x64asm;

namespace stoke {

void CfgTransforms::remove_unreachable(Cfg& cfg) {
  Code temp;
  for (auto b = cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
    for (auto i = cfg.instr_begin(*b), ie = cfg.instr_end(*b); i != ie; ++i) {
      temp.push_back(*i);
    }
  }

  cfg.get_code() = temp;
  cfg.recompute();
}

void CfgTransforms::remove_nop(Cfg& cfg) {
  Code temp;
  for (auto b = cfg.get_entry(), be = cfg.get_exit(); b != be; ++b) {
    for (auto i = cfg.instr_begin(b), ie = cfg.instr_end(b); i != ie; ++i) {
      if (!i->is_nop()) {
        temp.push_back(*i);
      }
    }
  }

  cfg.get_code() = temp;
  cfg.recompute();
}

/** Returns true if the instruction has any visible side-effect other than
control flow or effect on registers (e.g. memory writes, possibility of
signals, etc.). */
bool has_side_effect(x64asm::Instruction& instr) {
  return instr.is_memory_dereference() ||
         (instr.get_opcode() >= DIV_M16 && instr.get_opcode() <= DIVSS_XMM_XMM);
}

void CfgTransforms::remove_redundant(Cfg& cfg) {
  bool changed = true;
  while (changed) {
    // loop will terminate, as we remove at least one instruction in every iteration, except maybe the last one
    changed = false;
    Code temp;
    for (stoke::Cfg::reachable_iterator b = cfg.reachable_begin(), be = cfg.reachable_end(); b != be; ++b) {
      size_t c = 0;
      for (auto i = cfg.instr_begin(*b), ie = cfg.instr_end(*b); i != ie; ++i, ++c) {
        bool keep = true;
        if ((*i).is_label_defn() || (*i).is_any_jump() ||
            (*i).is_any_call() || (*i).is_any_return() ||
            (*i).is_any_loop()) {
          // we always keep control flow
        } else if (has_side_effect(*i)) {
          // we always keep instructions that have any side-effect other than
          // on the registers (hardware exceptions, memory writes, etc.)
        } else {
          auto instr_outputs = cfg.maybe_write_set(*i);
          auto live_regs_after_instruction = cfg.live_outs({*b, c});
          if ((instr_outputs & live_regs_after_instruction) == x64asm::RegSet::empty()) {
            // don't keep the instruction if it doesn't produce any values which
            // are live right after that instruction
            keep = false;
          }
        }

        if (keep) {
          temp.push_back(*i);
        } else {
          changed = true; // we removed an instruction
        }
      }
    }

    cfg.get_code() = temp;
    cfg.recompute();
  }
}

} // namespace stoke
<|endoftext|>