text:
#include <stdexcept>
#include <iostream>
#include <cmath>
#include <limits>
#include <fstream>
#include <string>
#include <boost/filesystem.hpp>
#include <UnitTest++/UnitTest++.h>

#include "../emccd_model.h"

using namespace coela;
using namespace std;

SUITE(CCD_model)
{
    using namespace emccd_detail;

    string test_suite_output_dir= string(UnitTestSuite::GetSuiteName()) + "_tests/";

    TEST(Run_Standard_Suite_Setup) {
        cout << "*** \""<< UnitTestSuite::GetSuiteName() <<"\" unit tests running ***" <<endl;
        boost::filesystem::create_directories(test_suite_output_dir);
    }

    TEST(integer_factorial) {
        CHECK_EQUAL(1ul, integer_factorial(0));
        CHECK_EQUAL(1ul, integer_factorial(1));
        CHECK_EQUAL(2ul, integer_factorial(2));
        CHECK_EQUAL(6ul, integer_factorial(3));
        CHECK_EQUAL(24ul, integer_factorial(4));

//        cout<<"Unsigned long max: " << numeric_limits<unsigned long>::max() <<endl;
//
//        double max_int_fac =1;
//        while (approx_factorial_double(max_int_fac) < numeric_limits<unsigned long>::max())
//            max_int_fac++;
//
//        cout<<"Implies max input for integer_factorial:"<<max_int_fac<<endl;

    }

    TEST(EMCCD_pars_write_to_file) {
        EmccdModelParams pars;

        pars.bias_pedestal=1.1;
        pars.readout_sigma=2.1;
        pars.photon_gain=3.1;
        pars.serial_CIC_rate=4.1;
        pars.N_EM_serial_register_stages=604;

        pars.write_to_file(test_suite_output_dir+"sample_EMCCD_model_pars.xml");
        EmccdModelParams loaded(test_suite_output_dir+"sample_EMCCD_model_pars.xml");
        CHECK_EQUAL(pars.photon_gain, loaded.photon_gain);
    }

    TEST(EMCCD_gain_PMF) {
        double gain = 100;

        CHECK_CLOSE(exp(-1/gain)/gain , low_flux_gain_pmf(1, gain, 1) , 1e-6);

        for (int n_photons = 1; n_photons<=10; ++n_photons) {
            double sum_probability=0;
            for (int x_out=n_photons; x_out<10000; ++x_out) {
                double PMF_val = low_flux_gain_pmf(n_photons, gain, x_out);
                CHECK(PMF_val>0);
                CHECK(PMF_val<1);
                sum_probability+=PMF_val;
            }
            //Any more stringent tests (than 1 percent) fail due to numerical roundoff in sum.
            CHECK_CLOSE(1.0, sum_probability,
                        0.01);
        }

    }

//
//    TEST(Write_gain_PMFs_to_file_for_inspection){
//        double gain =100;
//        for (int n_photons = 1; n_photons<=10; ++n_photons){
//            ofstream datfile(string(test_suite_output_dir+"EMCCD_gain_PMF_for_"+string_utils::itoa(n_photons)+"_photons.txt").c_str());
//            for (int x_out=n_photons; x_out<10000; ++x_out){
//                double PMF_val = EMCCD_gain_PMF_at_value(n_photons, gain, x_out);
//                datfile<<x_out<<" "<<PMF_val<<"\n";
//            }
//            datfile.close();
//        }
//    }

    int hist_max = 10000;
    void count_result(vector<unsigned int>& hist, int result){
        if (fixed < 0) {
            throw logic_error(
                "emccd gain variate should not produce negative values");
        }
        if (result < hist_max) {
            ++hist[result];
        }
    }

    TEST(gain_variates) {
        vector<unsigned long> seed;
        seed.push_back(11);
        seed.push_back(25);
        seed.push_back(35);
        seed.push_back(44);
        seed.push_back(55);
        seed.push_back(66);
        unuran::StreamWrapper::set_unuran_package_seed(seed,
                false);

        unuran::StreamWrapper rns1;
        double gain=100.0;

        size_t n_its_per_hist = 1e6;

        GainVariate var_gen(gain, rns1);

        //Test for low flux:
        for (int n_photons=1;
                n_photons!=FixedLowFluxGainVariate::n_photons_limit_for_low_flux; ++n_photons) {
            vector<unsigned int> fixed_results(hist_max, 0);
            vector<unsigned int> var_results(hist_max, 0);

            FixedLowFluxGainVariate fixed_gen(n_photons, gain, rns1);

////            check default constructor followed by assignment:
//            EMCCD_fixed_low_flux_gain_variate gen;
//            gen = EMCCD_fixed_low_flux_gain_variate(n_photons, gain, rns1);

            for (size_t i=0; i!=n_its_per_hist; ++i) {
                count_result(fixed_results, fixed_gen());
                count_result(var_results, var_gen(n_photons));
            }

            if (n_photons==0) {
                CHECK_EQUAL(n_its_per_hist, fixed_results[0]);
                CHECK_EQUAL(n_its_per_hist, var_results[0]);
            }

            for (int ind=0; ind<100; ++ind) {
                double predicted_num = n_its_per_hist *
                                        low_flux_gain_pmf(n_photons, gain, ind);

                CHECK_CLOSE(predicted_num, (double)fixed_results[ind] ,
                        max(5*sqrt(predicted_num), 5.0));
                CHECK_CLOSE(predicted_num, (double)var_results[ind] ,
                                        max(5*sqrt(predicted_num), 5.0));
            }

        }

        //Test for high flux:

        n_its_per_hist = 1e5;
        int n_photons =55; //test high flux
        {
            vector<unsigned int> high_flux_results(hist_max, 0);
            for (size_t i=0; i!=n_its_per_hist; ++i) {
                count_result(high_flux_results, var_gen(n_photons));
            }

//            actual_hist.write_to_file(
//                    test_suite_output_dir+"EMCCD_gain_var_"+
//                        to_string(n_photons)+"_actual_hist.txt");
        }
    }

}//end of test suite

max_stars_repo_name: timstaley/coelacanth

max_issues_repo_name: timstaley/coelacanth

max_forks_repo_name: timstaley/coelacanth


text:
/***
   HiCapTools.
   Copyright (c) 2017 Pelin Sahlén <pelin.akan@scilifelab.se>

	Permission is hereby granted, free of charge, to any person obtaining a
	copy of this software and associated documentation files (the "Software"),
	to deal in the Software with some restriction, including without limitation
	the rights to use, copy, modify, merge, publish, distribute the Software,
	and to permit persons to whom the Software is furnished to do so, subject to
	the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software. The Software shall not be used
	for commercial purposes.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
	PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
	OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***/

//
//  BackgroundInteractionFrequency.cpp
//  HiCapTools
//
//  Created by Pelin Sahlen and Anandashankar Anil.
//

#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
using namespace boost::accumulators;

#include "BackgroundInteractionFrequency.h"
#include "Global.h"
#include "linear.h"
#include <fstream>
#include <cmath>

///For Probe-Distal and Probe-Probe
void DetermineBackgroundLevels::CalculateMeanandStdRegress(std::string eName, int ExperimentNo, std::string DesignName, BG_signals& bglevelsloc, int binsize, std::string whichProx, int MinimumJunctionDistance, OutStream& log, int WindowSizeloc){

	expName= eName; //set experiment name

	std::map< int, int > nofentries_perBin; // required for calculating mean
	std::map< int, int > signal_square; // required for calculating stdev
    double sum_square, variance;
	int distance;
    std::string feature_id;

    std::map< int, Junction >::const_iterator iter;
	for(int i = 0; i < Design_NegCtrl[DesignName].Probes.size(); i++){
        feature_id = Design_NegCtrl[DesignName].Probes[i].feature_id;
        //////////Probe-distal
        if(whichProx=="ProbeDistal"){
			for (iter = Features[feature_id].proximities.junctions.begin(); iter != Features[feature_id].proximities.junctions.end(); ++iter){

				distance = iter->first - Design_NegCtrl[DesignName].Probes[i].end;

				int bin = abs(distance) / binsize;

				if(iter->second.paircount[ExperimentNo] > 0){

					if(bglevelsloc.mean.find(bin) == bglevelsloc.mean.end())
						bglevelsloc.mean[bin] = iter->second.paircount[ExperimentNo];
					else
						bglevelsloc.mean[bin] = bglevelsloc.mean[bin] + iter->second.paircount[ExperimentNo];

					if(nofentries_perBin.find(bin) == nofentries_perBin.end()){
						nofentries_perBin[bin] = 1;
						signal_square[bin] = (iter->second.paircount[ExperimentNo])*(iter->second.paircount[ExperimentNo]);
					}
					else{
						nofentries_perBin[bin] = nofentries_perBin[bin] + 1;
						signal_square[bin] = (signal_square[bin] + ((iter->second.paircount[ExperimentNo])*(iter->second.paircount[ExperimentNo])));
					}
				}
			}
		}
		///////////Probe-Probe
        else if(whichProx=="ProbeProbe"){
			for (auto iter = Features[feature_id].Inter_feature_ints.begin(); iter != Features[feature_id].Inter_feature_ints.end(); ++iter){

				distance = Features[feature_id].start - Features[(*iter).interacting_feature_id].start;

				if((Features[feature_id].FeatureType == 3 && Features[(*iter).interacting_feature_id].FeatureType == 3) && Features[feature_id].TranscriptName != Features[(*iter).interacting_feature_id].TranscriptName && (abs(distance) >= MinimumJunctionDistance)){

					int bin = abs(distance) / binsize;
					if((*iter).signal[ExperimentNo] > 0){
						if(bglevelsloc.mean.find(bin) == bglevelsloc.mean.end())
							bglevelsloc.mean[bin] = (*iter).signal[ExperimentNo];
						else
							bglevelsloc.mean[bin] = bglevelsloc.mean[bin] + (*iter).signal[ExperimentNo];

						if(nofentries_perBin.find(bin) == nofentries_perBin.end()){
							nofentries_perBin[bin] = 1;
							signal_square[bin] = ((*iter).signal[ExperimentNo])*((*iter).signal[ExperimentNo]);
						}
						else{
							nofentries_perBin[bin] = nofentries_perBin[bin] + 1;
							signal_square[bin] = (signal_square[bin] + (((*iter).signal[ExperimentNo])*((*iter).signal[ExperimentNo])));
						}
					}
				}
			}
		}
    }

// Calculate Mean and stdev
	std::map< int, double>::iterator it; // iterator for bin signals
	for (it = bglevelsloc.mean.begin(); it != bglevelsloc.mean.end(); ++it){
        bglevelsloc.samplesize[it->first] = nofentries_perBin[it->first];
        if(bglevelsloc.samplesize[it->first] == 0){
            it->second = 1; //Mean
        }
        else{
            it->second /= nofentries_perBin[it->first]; //Mean
        }
        if(bglevelsloc.samplesize[it->first] <= 1){
            bglevelsloc.stdev[it->first] = 0;
        }
        else{
            sum_square = ((it->second)*(it->second));
            sum_square /= (double(nofentries_perBin[it->first])); // Average Sum Squared
            variance = signal_square[it->first] - sum_square;
            variance /= (nofentries_perBin[it->first] -1);
            bglevelsloc.stdev[it->first] = sqrt(variance); //stdev
        }
	}

    int first25kb = ceil(25000/(double)binsize); // to exclude bins of first 25 kb from smoothing

    boost::accumulators::accumulator_set<double, stats<tag::rolling_mean> > acc(tag::rolling_window::window_size = (WindowSizeloc*2));
    boost::accumulators::accumulator_set<double, stats<tag::rolling_mean> > acc2(tag::rolling_window::window_size = (WindowSizeloc*2));

    int w = 0, z = 0, s = 0, a=0;
    std::deque< double > dm, ds, db, dwm, dws;

    // Put values into a queue
    for (it = bglevelsloc.mean.begin(); it != bglevelsloc.mean.end(); ++it){

        dm.push_back(it->second);
        ds.push_back(bglevelsloc.stdev[it->first]);
        db.push_back(it->first);

    }
    //Push the first WindowSize-1 elements into a queue
	if(dm.empty())
		log<<"No Element in dm Outloop"<<std::endl;

	bool firstpass=true;
    for(w = 0; w < (dm.size()); ++w){
		if(w < first25kb){
			bglevelsloc.smoothed[db[w]] = dm[w];
			bglevelsloc.smoothed_stdev[db[w]] = ds[w];
		}
		else{
			boost::accumulators::accumulator_set<double, stats<tag::rolling_mean> > acc(tag::rolling_window::window_size = (WindowSizeloc));
			boost::accumulators::accumulator_set<double, stats<tag::rolling_mean> > acc2(tag::rolling_window::window_size = (WindowSizeloc));

			if(w >= first25kb && w < first25kb + WindowSizeloc - 1){

				/**
				if(dwm.size()==WindowSizeloc){
					for(z = 0; z < WindowSizeloc;++z){
						std::cout<<dwm[z]<<std::endl;
					}
					dwm.pop_front();
				}
			**/
				//change to rolling mean if needed
				bglevelsloc.smoothed[db[w]] = dm[w];
				bglevelsloc.smoothed_stdev[db[w]] = ds[w];

			}
			else {
			    if(firstpass){
			        for(auto it=w-(WindowSizeloc/2); it<w+WindowSizeloc/2;++it){ //for the first bin that is to be smoothed
			            dwm.push_back(dm[it]);
			            dws.push_back(ds[it]);
			        }
			        firstpass=false;
			    }
				bool ifrolling=false;

				//To check that the window stops at the last bin
				if(w+WindowSizeloc/2 < dm.size()){
				    dwm.push_back(dm.at(w+WindowSizeloc/2));
				    dws.push_back(ds.at(w+WindowSizeloc/2));
				}

				if(dwm.size()==WindowSizeloc){
					ifrolling=true;
					for(z = 0; z < WindowSizeloc;++z){
						acc(dwm[z]);
						acc2(dws[z]);
					}
				}
				if(ifrolling){
					bglevelsloc.smoothed[db[w]] = rolling_mean(acc);
					bglevelsloc.smoothed_stdev[db[w]] = rolling_mean(acc2);

				}
				else{
					bglevelsloc.smoothed[db[w]] = dm[w];
					bglevelsloc.smoothed_stdev[db[w]] = ds[w];

				}

				dwm.pop_front();
				dws.pop_front();

			}
		}
	}
}

void DetermineBackgroundLevels::PrintBackgroundFrequency(int bSize, int bSizePP, PrDes::RENFileInfo& reInfo){

	std::string FileNamePE, FileNamePP;

	FileNamePE.append(expName);
	FileNamePE.append(".");
	FileNamePE.append(reInfo.genomeAssembly.substr(0, reInfo.genomeAssembly.find_first_of(',')));
	FileNamePE.append(".Probe_Distal.BackgroundLevels.");
	FileNamePE.append(reInfo.currTime);
	FileNamePE.append(".txt");

	FileNamePP.append(expName);
	FileNamePP.append(".");
	FileNamePP.append(reInfo.genomeAssembly.substr(0, reInfo.genomeAssembly.find_first_of(',')));
	FileNamePP.append(".Probe_Probe.BackgroundLevels.");
	FileNamePP.append(reInfo.currTime);
	FileNamePP.append(".txt");

	std::ofstream outfPE(FileNamePE.c_str());
	std::ofstream outfPP(FileNamePP.c_str());
    outfPE << "Distance Bin" << '\t' << "Interaction Distance" << '\t' << "Mean " << '\t' << "Stdev" << '\t' << "Sample Size" << '\t' << "Mean (Smoothed)" << '\t' << "StDev (Smoothed)" <<  std::endl;

	for (auto it = bglevels.smoothed.begin(); it != bglevels.smoothed.end(); ++it){
        outfPE << (it->first) << '\t'<< (it->first)*bSize << '\t' << bglevels.mean[it->first] << '\t' << bglevels.stdev[it->first] << '\t' << bglevels.samplesize[it->first] << '\t' << it->second << '\t' << bglevels.smoothed_stdev[it->first] << std::endl;
	}

	outfPP << "Distance Bin" << '\t' << "Interaction Distance" << '\t' << "Mean " << '\t' << "Stdev" << '\t' << "Sample Size" << '\t' << "Mean (Smoothed)" << '\t' << "StDev (Smoothed)" <<  std::endl;

	for (auto it = bglevelsProbeProbe.smoothed.begin(); it != bglevelsProbeProbe.smoothed.end(); ++it){
        outfPP << (it->first) << '\t' << (it->first)*bSizePP << '\t' << bglevelsProbeProbe.mean[it->first] << '\t' << bglevelsProbeProbe.stdev[it->first] << '\t' << bglevelsProbeProbe.samplesize[it->first] << '\t' << it->second << '\t' << bglevelsProbeProbe.smoothed_stdev[it->first] << std::endl;
	}

}

ext: cpp

max_stars_repo_name: aanil/HiCapTools

max_issues_repo_name: aanil/HiCapTools

max_forks_repo_name: aanil/HiCapTools


text:
#pragma once

#include <Eigen/Core>

#include <memory>
#include <utility>
#include <vector>

namespace eq {
    const int INIT_TIME       = 0;
    const double MAX_MIN_DIFF = 10e-10;
    const double DEFAULT_STEP = 0.1;

    const double TASK_DIFF_STEP = 0.001;
    const double MAX_TIME_RUNGE = 0.2;
    const double MAX_TIME_DP    = 10;

    struct task_answer {
        double answer_max_diff_runge{-1};
        double answer_step_runge{-1};
        double answer_min_step_dp{-1};
        int answer_total_steps_dp{-1};
    };

    class EquationSolver;

    class Solver {
    public:
        virtual ~Solver() = default;
        explicit Solver(EquationSolver &eq_solver, double step) : _solver(eq_solver), _step(step) {}

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

        virtual void Calculate() = 0;
        virtual void Solver_set_matrix() = 0;

        Eigen::MatrixXd Generate_mat();

        double Get_step() const { return _step; }
        void Set_step(double step) {_step = step; }

    protected:
        EquationSolver &_solver;
        double _step;
    };

    class RungeSolver : public Solver {
    public:
        explicit RungeSolver(EquationSolver &eq_solver, double step = DEFAULT_STEP) : Solver(eq_solver, step) {}

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

        void Calculate() override;
        void Solver_set_matrix() override;

    private:
        void calc_step();
    };

    class DPSolver : public Solver {
    public:
        explicit DPSolver(EquationSolver &eq_solver, double max_diff = MAX_MIN_DIFF, double min_diff = MAX_MIN_DIFF,
                          double step = DEFAULT_STEP) :
                          Solver(eq_solver, step), _max_diff(max_diff), _min_diff(min_diff) {}

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

        void Calculate() override;
        void Solver_set_matrix() override;

    private:
        void calc_step();

    private:
        double _max_diff;
        double _min_diff;
    };

    class EquationSolver {
    public:
        explicit EquationSolver(std::function<Eigen::VectorXd(double, const Eigen::VectorXd &)> recalc_function,
                        Eigen::VectorXd start_vals, double start_time, std::function<Eigen::VectorXd(double)> result_function) :
                        _recalc_function(std::move(recalc_function)), _values(std::move(start_vals)), _time(start_time),
                        _result_function(std::move(result_function)) {}

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

        void Set_solver(std::unique_ptr<Solver>&& solver);
        void Reload_values(const Eigen::VectorXd &init_vals, double init_time);

        void Solve();
        task_answer Get_answer() const;

        double Get_time() const { return _time; }
        Eigen::VectorXd& Get_values() { return _values; }

    public:
        friend Solver;
        friend RungeSolver;
        friend DPSolver;

    private:
        std::unique_ptr<Solver> _solver;

        std::function<Eigen::VectorXd(double, const Eigen::VectorXd &)> _recalc_function;
        Eigen::VectorXd _values;
        Eigen::VectorXd _steps;
        std::function<Eigen::VectorXd(double)> _result_function;

        Eigen::MatrixXd _a;
        std::vector<Eigen::MatrixXd> _b;

        double _time{0};

    private:
        double _answer_max_diff_runge{-1};
        double _answer_step_runge{-1};
        double _answer_min_step_dp{-1};
        int _answer_total_steps_dp{-1};
    };

    task_answer Calculate(std::function<Eigen::VectorXd(double, const Eigen::VectorXd &)> src_function,
                   std::function<Eigen::VectorXd(double)> result_function, const Eigen::VectorXd& init_val);
}

ext: hpp


text:
#include "ini-files.h"

#include <iostream>

#include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

namespace ts7 {
  namespace jsonrpc_playground {
    namespace ini {
      namespace v2 {
        /**
         * @brief Configuration
         *
         * Class that maps configuration values of a property tree to a named structure.
         *
         * @tparam TData Data type of the structure that shall be used to store the read values.
         *
         * @since 1.0
         *
         * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
         */
        template <typename TData>
        struct Configuration {
            /**
             * @brief Configuration entry
             *
             * Represents a single entry in the configuration.
             *
             * @tparam T Data type of the configuration entry.
             *
             * @param identifier Identifier of the configuration entry.
             * @param offset Pointer to the member variable that needs to be filled.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            template <typename T>
            struct Entry {
              /**
               * @brief constructor
               *
               * Creates a configuration entry without a default value.
               *
               * @param identifier Identifier of the entry.
               * @param offset Pointer to the structure data member.
               *
               * @since 1.0
               *
               * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
               */
              inline Entry(const char* identifier, T TData::* offset)
                : identifier(identifier),
                  offset(offset),
                  defaultValue(T()),
                  hasDefault(false)
              {}

              /**
               * @brief constructor
               *
               * Creates a configuration entry with a default value.
               *
               * @param identifier Identifier of the configuration entry.
               * @param offset Pointer to the data member to store the value.
               * @param defaultValue Default value, if the configuration entry can't be found.
               *
               * @since 1.0
               *
               * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
               */
              inline Entry(const char* identifier, T TData::* offset, T defaultValue)
                : identifier(identifier),
                  offset(offset),
                  defaultValue(defaultValue),
                  hasDefault(true)
              {}

              /**
               * @brief read
               *
               * Reads the configuration value and stores in the corresponding member of the
               * provided data structure.
               *
               * @param pt Property tree that contains the entry.
               * @param data Reference to the data structure that shall be filled.
               *
               * @since 1.0
               *
               * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
               */
              inline void read(boost::property_tree::ptree& pt, TData& data) {
                if (hasDefault) {
                  data.*offset = pt.get<T>(identifier, defaultValue);
                }
                else {
                  data.*offset = pt.get<T>(identifier);
                }
              }

              /// Path the configuration entry
              const char* identifier;

              /// Pointer to the member that shall be filled
              T TData::* offset;

              /// Default value, if a default value was provided
              T defaultValue;

              /// True, if a default value exists. Otherwise it is False.
              const bool hasDefault;
            };

            /**
             * @brief Add entry
             *
             * Adds a new entry without a default value.
             *
             * @tparam T Data type of the configuration entry.
             *
             * @param identifier Identifier of the configuration entry.
             * @param offset Pointer to the data member.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            template <typename T>
            void add(const char* identifier, T TData::* offset) {
              add(Entry<T>(identifier, offset));
            }

            /**
             * @brief Add entry
             *
             * Adds a new entry with a default value.
             *
             * @tparam T Data type of the configuration entry.
             *
             * @param identifier Identifier of the configuration entry.
             * @param offset Pointer to the data member.
             * @param defaultValue Default value, if the configuration entry can't be found.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            template <typename T>
            void add(const char* identifier, T TData::* offset, const T& defaultValue) {
              add(Entry<T>(identifier, offset, defaultValue));
            }

            /**
             * @brief add int
             *
             * Adds an integer entry.
             *
             * @param e The entry that shall be created.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            inline void add(const Entry<int>& e) {
              integers.push_back(e);
            }

            /**
             * @brief add string
             *
             * Adds a string entry.
             *
             * @param e The entry that shall be created.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            inline void add(const Entry<std::string>& e) {
              strings.push_back(e);
            }

            /**
             * @brief read
             *
             * Reads the INI file to a property tree and then transfers the values with
             * the entries to the data structure.
             *
             * @param filename Name of the file that shall be read.
             * @param data Data that shall be filed.
             *
             * @since 1.0
             *
             * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
             */
            void read(const char* filename, TData& data) {
              boost::property_tree::ptree pt;

              if (boost::filesystem::exists(filename)) {
                boost::property_tree::ini_parser::read_ini(filename, pt);
              }

              for (Entry<int>& e : integers) {
                e.read(pt, data);
              }

              for (Entry<std::string>& e : strings) {
                e.read(pt, data);
              }
            }

            std::vector<Entry<int>> integers;
            std::vector<Entry<std::string>> strings;
        };

        /**
         * @brief Test struct
         *
         * Dummy structure to test reading integer and string.
         *
         * @since 1.0
         *
         * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
         */
        struct Test {
            std::string Str;
            int Int;
        };

        /**
         * @brief Read to struct
         *
         * Demonstrates how to read data from an INI file to a struct.
         *
         * @since 1.0
         *
         * @author Tarek Schwarzinger <tarek.schwarzinger@googlemail.com>
         */
        void structured() {
          std::cout << "##### " << __PRETTY_FUNCTION__ << " #####" << std::endl;

          boost::property_tree::ptree pt;

          if (boost::filesystem::exists("test.ini")) {
          boost::property_tree::ini_parser::read_ini("test.ini", pt);
          }
          else {
            std::cout << "test.ini does not exists" << std::endl;
          }

          Test t1;
          t1.Str = "Hello World";
          t1.Int = 3;

          std::cout << "t1.Str=" << t1.Str << " (pre)" << std::endl;
          std::cout << "t1.Int=" << t1.Int << " (pre)" << std::endl;

          Configuration<Test> configuration;
          configuration.add("Str", &Test::Str, std::string("Bye bye"));
          configuration.add("Int", &Test::Int, 7);
          configuration.read("test.ini", t1);

          std::cout << "t1.Str=" << t1.Str << " (post)" << std::endl;
          std::cout << "t1.Int=" << t1.Int << " (post)" << std::endl;
        }
      }
    }
  }
}


text:
#ifndef CPP_WEB_SERVER_HTTP_SERVER_HPP
#define CPP_WEB_SERVER_HTTP_SERVER_HPP

#include "async_web_server_cpp/http_connection.hpp"
#include "async_web_server_cpp/http_request_handler.hpp"

#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>

#include <string>
#include <vector>

namespace async_web_server_cpp
{

/**
 * @class HttpServer
 * The HttpServer is an implementation of a HTTP server that serves http request
 * from a given port The server maintains a pool of threads to use to serve
 * requests. Each request is dispatched to the given request handler to be
 * handled.
 */
class HttpServer : private boost::noncopyable
{
public:
    HttpServer(const std::string& address, const std::string& port,
               HttpServerRequestHandler request_handler,
               std::size_t thread_pool_size);
    ~HttpServer();

    void run();

    void stop();

private:
    void start_accept();

    void handle_accept(const boost::system::error_code& e);

    boost::asio::io_service io_service_;
    boost::asio::ip::tcp::acceptor acceptor_;
    std::size_t thread_pool_size_;
    std::vector<boost::shared_ptr<boost::thread>> threads_;
    boost::shared_ptr<HttpConnection> new_connection_;
    HttpServerRequestHandler request_handler_;
};

}  // namespace async_web_server_cpp

#endif


text:
/**
 * @file serialization_test.cpp
 * @author Ryan Curtin
 *
 * Test serialization of mlpack objects.
 */
#include <mlpack/core.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"
#include "serialization.hpp"

#include <mlpack/core/dists/regression_distribution.hpp>
#include <mlpack/core/tree/ballbound.hpp>
#include <mlpack/core/tree/hrectbound.hpp>
#include <mlpack/core/metrics/mahalanobis_distance.hpp>
#include <mlpack/core/tree/binary_space_tree.hpp>
#include <mlpack/methods/hoeffding_trees/hoeffding_tree.hpp>
#include <mlpack/core/tree/cover_tree.hpp>
#include <mlpack/core/tree/rectangle_tree.hpp>

#include <mlpack/methods/perceptron/perceptron.hpp>
#include <mlpack/methods/logistic_regression/logistic_regression.hpp>
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
#include <mlpack/methods/softmax_regression/softmax_regression.hpp>
#include <mlpack/methods/det/dtree.hpp>
#include <mlpack/methods/naive_bayes/naive_bayes_classifier.hpp>
#include <mlpack/methods/rann/ra_search.hpp>
#include <mlpack/methods/lsh/lsh_search.hpp>
#include <mlpack/methods/decision_stump/decision_stump.hpp>
#include <mlpack/methods/lars/lars.hpp>

using namespace mlpack;
using namespace mlpack::distribution;
using namespace mlpack::regression;
using namespace mlpack::bound;
using namespace mlpack::metric;
using namespace mlpack::tree;
using namespace mlpack::perceptron;
using namespace mlpack::regression;
using namespace mlpack::naive_bayes;
using namespace mlpack::neighbor;
using namespace mlpack::decision_stump;

using namespace arma;
using namespace boost;
using namespace boost::archive;
using namespace boost::serialization;
using namespace std;

BOOST_AUTO_TEST_SUITE(SerializationTest);

/**
 * Serialize a random cube.
 */
BOOST_AUTO_TEST_CASE(CubeSerializeTest)
{
  arma::cube m;
  m.randu(2, 50, 50);
  TestAllArmadilloSerialization(m);
}

/**
 * Serialize an empty cube.
 */
BOOST_AUTO_TEST_CASE(EmptyCubeSerializeTest)
{
  arma::cube c;
  TestAllArmadilloSerialization(c);
}

/**
 * Can we load and save an Armadillo matrix?
 */
BOOST_AUTO_TEST_CASE(MatrixSerializeXMLTest)
{
  arma::mat m;
  m.randu(50, 50);
  TestAllArmadilloSerialization(m);
}

/**
 * How about columns?
 */
BOOST_AUTO_TEST_CASE(ColSerializeTest)
{
  arma::vec m;
  m.randu(50, 1);
  TestAllArmadilloSerialization(m);
}

/**
 * How about rows?
 */
BOOST_AUTO_TEST_CASE(RowSerializeTest)
{
  arma::rowvec m;
  m.randu(1, 50);
  TestAllArmadilloSerialization(m);
}

// A quick test with an empty matrix.
BOOST_AUTO_TEST_CASE(EmptyMatrixSerializeTest)
{
  arma::mat m;
  TestAllArmadilloSerialization(m);
}

/**
 * Can we load and save a sparse Armadillo matrix?
 */
BOOST_AUTO_TEST_CASE(SparseMatrixSerializeTest)
{
  arma::sp_mat m;
  m.sprandu(50, 50, 0.3);
  TestAllArmadilloSerialization(m);
}

/**
 * How about columns?
 */
BOOST_AUTO_TEST_CASE(SparseColSerializeTest)
{
  arma::sp_vec m;
  m.sprandu(50, 1, 0.3);
  TestAllArmadilloSerialization(m);
}

/**
 * How about rows?
 */
BOOST_AUTO_TEST_CASE(SparseRowSerializeTest)
{
  arma::sp_rowvec m;
  m.sprandu(1, 50, 0.3);
  TestAllArmadilloSerialization(m);
}

// A quick test with an empty matrix.
BOOST_AUTO_TEST_CASE(EmptySparseMatrixSerializeTest)
{
  arma::sp_mat m;
  TestAllArmadilloSerialization(m);
}

// Now, test mlpack objects.
BOOST_AUTO_TEST_CASE(DiscreteDistributionTest)
{
  // I assume that I am properly saving vectors, so, this should be
  // straightforward.
  vec prob;
  prob.randu(12);
  DiscreteDistribution t(prob);

  DiscreteDistribution xmlT, textT, binaryT;

  // Load and save with all serializers.
  SerializeObjectAll(t, xmlT, textT, binaryT);

  for (size_t i = 0; i < 12; ++i)
  {
    vec obs(1);
    obs[0] = i;
    const double prob = t.Probability(obs);
    if (prob == 0.0)
    {
      BOOST_REQUIRE_SMALL(xmlT.Probability(obs), 1e-8);
      BOOST_REQUIRE_SMALL(textT.Probability(obs), 1e-8);
      BOOST_REQUIRE_SMALL(binaryT.Probability(obs), 1e-8);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(prob, xmlT.Probability(obs), 1e-8);
      BOOST_REQUIRE_CLOSE(prob, textT.Probability(obs), 1e-8);
      BOOST_REQUIRE_CLOSE(prob, binaryT.Probability(obs), 1e-8);
    }
  }
}

BOOST_AUTO_TEST_CASE(GaussianDistributionTest)
{
  vec mean(10);
  mean.randu();
  // Generate a covariance matrix.
  mat cov;
  cov.randu(10, 10);
  cov = (cov * cov.t());

  GaussianDistribution g(mean, cov);
  GaussianDistribution xmlG, textG, binaryG;

  SerializeObjectAll(g, xmlG, textG, binaryG);

  BOOST_REQUIRE_EQUAL(g.Dimensionality(), xmlG.Dimensionality());
  BOOST_REQUIRE_EQUAL(g.Dimensionality(), textG.Dimensionality());
  BOOST_REQUIRE_EQUAL(g.Dimensionality(), binaryG.Dimensionality());

  // First, check the means.
  CheckMatrices(g.Mean(), xmlG.Mean(), textG.Mean(), binaryG.Mean());

  // Now, check the covariance.
  CheckMatrices(g.Covariance(), xmlG.Covariance(), textG.Covariance(),
      binaryG.Covariance());

  // Lastly, run some observations through and make sure the probability is the
  // same.  This should test anything cached internally.
  arma::mat randomObs;
  randomObs.randu(10, 500);

  for (size_t i = 0; i < 500; ++i)
  {
    const double prob = g.Probability(randomObs.unsafe_col(i));

    if (prob == 0.0)
    {
      BOOST_REQUIRE_SMALL(xmlG.Probability(randomObs.unsafe_col(i)), 1e-8);
      BOOST_REQUIRE_SMALL(textG.Probability(randomObs.unsafe_col(i)), 1e-8);
      BOOST_REQUIRE_SMALL(binaryG.Probability(randomObs.unsafe_col(i)), 1e-8);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(prob, xmlG.Probability(randomObs.unsafe_col(i)),
          1e-8);
      BOOST_REQUIRE_CLOSE(prob, textG.Probability(randomObs.unsafe_col(i)),
          1e-8);
      BOOST_REQUIRE_CLOSE(prob, binaryG.Probability(randomObs.unsafe_col(i)),
          1e-8);
    }
  }
}

BOOST_AUTO_TEST_CASE(LaplaceDistributionTest)
{
  vec mean(20);
  mean.randu();

  LaplaceDistribution l(mean, 2.5);
  LaplaceDistribution xmlL, textL, binaryL;

  SerializeObjectAll(l, xmlL, textL, binaryL);

  BOOST_REQUIRE_CLOSE(l.Scale(), xmlL.Scale(), 1e-8);
  BOOST_REQUIRE_CLOSE(l.Scale(), textL.Scale(), 1e-8);
  BOOST_REQUIRE_CLOSE(l.Scale(), binaryL.Scale(), 1e-8);

  CheckMatrices(l.Mean(), xmlL.Mean(), textL.Mean(), binaryL.Mean());
}

BOOST_AUTO_TEST_CASE(MahalanobisDistanceTest)
{
  MahalanobisDistance<> d;
  d.Covariance().randu(50, 50);

  MahalanobisDistance<> xmlD, textD, binaryD;

  SerializeObjectAll(d, xmlD, textD, binaryD);

  // Check the covariance matrices.
  CheckMatrices(d.Covariance(),
                xmlD.Covariance(),
                textD.Covariance(),
                binaryD.Covariance());
}

BOOST_AUTO_TEST_CASE(LinearRegressionTest)
{
  // Generate some random data.
  mat data;
  data.randn(15, 800);
  vec responses;
  responses.randn(800, 1);

  LinearRegression lr(data, responses, 0.05); // Train the model.
  LinearRegression xmlLr, textLr, binaryLr;

  SerializeObjectAll(lr, xmlLr, textLr, binaryLr);

  BOOST_REQUIRE_CLOSE(lr.Lambda(), xmlLr.Lambda(), 1e-8);
  BOOST_REQUIRE_CLOSE(lr.Lambda(), textLr.Lambda(), 1e-8);
  BOOST_REQUIRE_CLOSE(lr.Lambda(), binaryLr.Lambda(), 1e-8);

  CheckMatrices(lr.Parameters(), xmlLr.Parameters(), textLr.Parameters(),
      binaryLr.Parameters());
}

BOOST_AUTO_TEST_CASE(RegressionDistributionTest)
{
  // Generate some random data.
  mat data;
  data.randn(15, 800);
  vec responses;
  responses.randn(800, 1);

  RegressionDistribution rd(data, responses);
  RegressionDistribution xmlRd, textRd, binaryRd;

  // Okay, now save it and load it.
  SerializeObjectAll(rd, xmlRd, textRd, binaryRd);

  // Check the gaussian distribution.
  CheckMatrices(rd.Err().Mean(),
                xmlRd.Err().Mean(),
                textRd.Err().Mean(),
                binaryRd.Err().Mean());
  CheckMatrices(rd.Err().Covariance(),
                xmlRd.Err().Covariance(),
                textRd.Err().Covariance(),
                binaryRd.Err().Covariance());

  // Check the regression function.
  if (rd.Rf().Lambda() == 0.0)
  {
    BOOST_REQUIRE_SMALL(xmlRd.Rf().Lambda(), 1e-8);
    BOOST_REQUIRE_SMALL(textRd.Rf().Lambda(), 1e-8);
    BOOST_REQUIRE_SMALL(binaryRd.Rf().Lambda(), 1e-8);
  }
  else
  {
    BOOST_REQUIRE_CLOSE(rd.Rf().Lambda(), xmlRd.Rf().Lambda(), 1e-8);
    BOOST_REQUIRE_CLOSE(rd.Rf().Lambda(), textRd.Rf().Lambda(), 1e-8);
    BOOST_REQUIRE_CLOSE(rd.Rf().Lambda(), binaryRd.Rf().Lambda(), 1e-8);
  }

  CheckMatrices(rd.Rf().Parameters(),
                xmlRd.Rf().Parameters(),
                textRd.Rf().Parameters(),
                binaryRd.Rf().Parameters());
}

BOOST_AUTO_TEST_CASE(BallBoundTest)
{
  BallBound<> b(100);
  b.Center().randu();
  b.Radius() = 14.0;

  BallBound<> xmlB, textB, binaryB;

  SerializeObjectAll(b, xmlB, textB, binaryB);

  // Check the dimensionality.
  BOOST_REQUIRE_EQUAL(b.Dim(), xmlB.Dim());
  BOOST_REQUIRE_EQUAL(b.Dim(), textB.Dim());
  BOOST_REQUIRE_EQUAL(b.Dim(), binaryB.Dim());

  // Check the radius.
  BOOST_REQUIRE_CLOSE(b.Radius(), xmlB.Radius(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.Radius(), textB.Radius(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.Radius(), binaryB.Radius(), 1e-8);

  // Now check the vectors.
  CheckMatrices(b.Center(), xmlB.Center(), textB.Center(), binaryB.Center());
}

BOOST_AUTO_TEST_CASE(MahalanobisBallBoundTest)
{
  BallBound<arma::vec, MahalanobisDistance<>> b(100);
  b.Center().randu();
  b.Radius() = 14.0;
  b.Metric().Covariance().randu(100, 100);

  BallBound<arma::vec, MahalanobisDistance<>> xmlB, textB, binaryB;

  SerializeObjectAll(b, xmlB, textB, binaryB);

  // Check the radius.
  BOOST_REQUIRE_CLOSE(b.Radius(), xmlB.Radius(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.Radius(), textB.Radius(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.Radius(), binaryB.Radius(), 1e-8);

  // Check the vectors.
  CheckMatrices(b.Center(), xmlB.Center(), textB.Center(), binaryB.Center());
  CheckMatrices(b.Metric().Covariance(),
                xmlB.Metric().Covariance(),
                textB.Metric().Covariance(),
                binaryB.Metric().Covariance());
}

BOOST_AUTO_TEST_CASE(HRectBoundTest)
{
  HRectBound<> b(2);

  arma::mat points("0.0, 1.1; 5.0, 2.2");
  points = points.t();
  b |= points; // [0.0, 5.0]; [1.1, 2.2];

  HRectBound<> xmlB, textB, binaryB;

  SerializeObjectAll(b, xmlB, textB, binaryB);

  // Check the dimensionality.
  BOOST_REQUIRE_EQUAL(b.Dim(), xmlB.Dim());
  BOOST_REQUIRE_EQUAL(b.Dim(), textB.Dim());
  BOOST_REQUIRE_EQUAL(b.Dim(), binaryB.Dim());

  // Check the bounds.
  for (size_t i = 0; i < b.Dim(); ++i)
  {
    BOOST_REQUIRE_CLOSE(b[i].Lo(), xmlB[i].Lo(), 1e-8);
    BOOST_REQUIRE_CLOSE(b[i].Hi(), xmlB[i].Hi(), 1e-8);
    BOOST_REQUIRE_CLOSE(b[i].Lo(), textB[i].Lo(), 1e-8);
    BOOST_REQUIRE_CLOSE(b[i].Hi(), textB[i].Hi(), 1e-8);
    BOOST_REQUIRE_CLOSE(b[i].Lo(), binaryB[i].Lo(), 1e-8);
    BOOST_REQUIRE_CLOSE(b[i].Hi(), binaryB[i].Hi(), 1e-8);
  }

  // Check the minimum width.
  BOOST_REQUIRE_CLOSE(b.MinWidth(), xmlB.MinWidth(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.MinWidth(), textB.MinWidth(), 1e-8);
  BOOST_REQUIRE_CLOSE(b.MinWidth(), binaryB.MinWidth(), 1e-8);
}

template<typename TreeType>
void CheckTrees(TreeType& tree,
                TreeType& xmlTree,
                TreeType& textTree,
                TreeType& binaryTree)
{
  const typename TreeType::Mat* dataset = &tree.Dataset();

  // Make sure that the data matrices are the same.
  if (tree.Parent() == NULL)
  {
    CheckMatrices(*dataset,
                  xmlTree.Dataset(),
                  textTree.Dataset(),
                  binaryTree.Dataset());

    // Also ensure that the other parents are null too.
    BOOST_REQUIRE_EQUAL(xmlTree.Parent(), (TreeType*) NULL);
    BOOST_REQUIRE_EQUAL(textTree.Parent(), (TreeType*) NULL);
    BOOST_REQUIRE_EQUAL(binaryTree.Parent(), (TreeType*) NULL);
  }

  // Make sure the number of children is the same.
  BOOST_REQUIRE_EQUAL(tree.NumChildren(), xmlTree.NumChildren());
  BOOST_REQUIRE_EQUAL(tree.NumChildren(), textTree.NumChildren());
  BOOST_REQUIRE_EQUAL(tree.NumChildren(), binaryTree.NumChildren());

  // Make sure the number of descendants is the same.
  BOOST_REQUIRE_EQUAL(tree.NumDescendants(), xmlTree.NumDescendants());
  BOOST_REQUIRE_EQUAL(tree.NumDescendants(), textTree.NumDescendants());
  BOOST_REQUIRE_EQUAL(tree.NumDescendants(), binaryTree.NumDescendants());

  // Make sure the number of points is the same.
  BOOST_REQUIRE_EQUAL(tree.NumPoints(), xmlTree.NumPoints());
  BOOST_REQUIRE_EQUAL(tree.NumPoints(), textTree.NumPoints());
  BOOST_REQUIRE_EQUAL(tree.NumPoints(), binaryTree.NumPoints());

  // Check that each point is the same.
  for (size_t i = 0; i < tree.NumPoints(); ++i)
  {
    BOOST_REQUIRE_EQUAL(tree.Point(i), xmlTree.Point(i));
    BOOST_REQUIRE_EQUAL(tree.Point(i), textTree.Point(i));
    BOOST_REQUIRE_EQUAL(tree.Point(i), binaryTree.Point(i));
  }

  // Check that the parent distance is the same.
  BOOST_REQUIRE_CLOSE(tree.ParentDistance(), xmlTree.ParentDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.ParentDistance(), textTree.ParentDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.ParentDistance(), binaryTree.ParentDistance(), 1e-8);

  // Check that the furthest descendant distance is the same.
  BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
      xmlTree.FurthestDescendantDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
      textTree.FurthestDescendantDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.FurthestDescendantDistance(),
      binaryTree.FurthestDescendantDistance(), 1e-8);

  // Check that the minimum bound distance is the same.
  BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
      xmlTree.MinimumBoundDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
      textTree.MinimumBoundDistance(), 1e-8);
  BOOST_REQUIRE_CLOSE(tree.MinimumBoundDistance(),
      binaryTree.MinimumBoundDistance(), 1e-8);

  // Recurse into the children.
  for (size_t i = 0; i < tree.NumChildren(); ++i)
  {
    // Check that the child dataset is the same.
    BOOST_REQUIRE_EQUAL(&xmlTree.Dataset(), &xmlTree.Child(i).Dataset());
    BOOST_REQUIRE_EQUAL(&textTree.Dataset(), &textTree.Child(i).Dataset());
    BOOST_REQUIRE_EQUAL(&binaryTree.Dataset(), &binaryTree.Child(i).Dataset());

    // Make sure the parent link is right.
    BOOST_REQUIRE_EQUAL(xmlTree.Child(i).Parent(), &xmlTree);
    BOOST_REQUIRE_EQUAL(textTree.Child(i).Parent(), &textTree);
    BOOST_REQUIRE_EQUAL(binaryTree.Child(i).Parent(), &binaryTree);

    CheckTrees(tree.Child(i), xmlTree.Child(i), textTree.Child(i),
        binaryTree.Child(i));
  }
}

BOOST_AUTO_TEST_CASE(BinarySpaceTreeTest)
{
  arma::mat data;
  data.randu(3, 100);
  typedef KDTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
  TreeType tree(data);

  TreeType* xmlTree;
  TreeType* textTree;
  TreeType* binaryTree;

  SerializePointerObjectAll(&tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, *xmlTree, *textTree, *binaryTree);

  delete xmlTree;
  delete textTree;
  delete binaryTree;
}

BOOST_AUTO_TEST_CASE(BinarySpaceTreeOverwriteTest)
{
  arma::mat data;
  data.randu(3, 100);
  typedef KDTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
  TreeType tree(data);

  arma::mat otherData;
  otherData.randu(5, 50);
  TreeType xmlTree(otherData);
  TreeType textTree(xmlTree);
  TreeType binaryTree(xmlTree);

  SerializeObjectAll(tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, xmlTree, textTree, binaryTree);
}

BOOST_AUTO_TEST_CASE(CoverTreeTest)
{
  arma::mat data;
  data.randu(3, 100);
  typedef StandardCoverTree<EuclideanDistance, EmptyStatistic, arma::mat>
      TreeType;
  TreeType tree(data);

  TreeType* xmlTree;
  TreeType* textTree;
  TreeType* binaryTree;

  SerializePointerObjectAll(&tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, *xmlTree, *textTree, *binaryTree);

  // Also check a few other things.
  std::stack<TreeType*> stack, xmlStack, textStack, binaryStack;
  stack.push(&tree);
  xmlStack.push(xmlTree);
  textStack.push(textTree);
  binaryStack.push(binaryTree);
  while (!stack.empty())
  {
    TreeType* node = stack.top();
    TreeType* xmlNode = xmlStack.top();
    TreeType* textNode = textStack.top();
    TreeType* binaryNode = binaryStack.top();
    stack.pop();
    xmlStack.pop();
    textStack.pop();
    binaryStack.pop();

    BOOST_REQUIRE_EQUAL(node->Scale(), xmlNode->Scale());
    BOOST_REQUIRE_EQUAL(node->Scale(), textNode->Scale());
    BOOST_REQUIRE_EQUAL(node->Scale(), binaryNode->Scale());

    BOOST_REQUIRE_CLOSE(node->Base(), xmlNode->Base(), 1e-5);
    BOOST_REQUIRE_CLOSE(node->Base(), textNode->Base(), 1e-5);
    BOOST_REQUIRE_CLOSE(node->Base(), binaryNode->Base(), 1e-5);

    for (size_t i = 0; i < node->NumChildren(); ++i)
    {
      stack.push(&node->Child(i));
      xmlStack.push(&xmlNode->Child(i));
      textStack.push(&textNode->Child(i));
      binaryStack.push(&binaryNode->Child(i));
    }
  }

  delete xmlTree;
  delete textTree;
  delete binaryTree;
}

BOOST_AUTO_TEST_CASE(CoverTreeOverwriteTest)
{
  arma::mat data;
  data.randu(3, 100);
  typedef StandardCoverTree<EuclideanDistance, EmptyStatistic, arma::mat>
      TreeType;
  TreeType tree(data);

  arma::mat otherData;
  otherData.randu(5, 50);
  TreeType xmlTree(otherData);
  TreeType textTree(xmlTree);
  TreeType binaryTree(xmlTree);

  SerializeObjectAll(tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, xmlTree, textTree, binaryTree);

  // Also check a few other things.
  std::stack<TreeType*> stack, xmlStack, textStack, binaryStack;
  stack.push(&tree);
  xmlStack.push(&xmlTree);
  textStack.push(&textTree);
  binaryStack.push(&binaryTree);
  while (!stack.empty())
  {
    TreeType* node = stack.top();
    TreeType* xmlNode = xmlStack.top();
    TreeType* textNode = textStack.top();
    TreeType* binaryNode = binaryStack.top();
    stack.pop();
    xmlStack.pop();
    textStack.pop();
    binaryStack.pop();

    BOOST_REQUIRE_EQUAL(node->Scale(), xmlNode->Scale());
    BOOST_REQUIRE_EQUAL(node->Scale(), textNode->Scale());
    BOOST_REQUIRE_EQUAL(node->Scale(), binaryNode->Scale());

    BOOST_REQUIRE_CLOSE(node->Base(), xmlNode->Base(), 1e-5);
    BOOST_REQUIRE_CLOSE(node->Base(), textNode->Base(), 1e-5);
    BOOST_REQUIRE_CLOSE(node->Base(), binaryNode->Base(), 1e-5);

    for (size_t i = 0; i < node->NumChildren(); ++i)
    {
      stack.push(&node->Child(i));
      xmlStack.push(&xmlNode->Child(i));
      textStack.push(&textNode->Child(i));
      binaryStack.push(&binaryNode->Child(i));
    }
  }
}

BOOST_AUTO_TEST_CASE(RectangleTreeTest)
{
  arma::mat data;
  data.randu(3, 1000);
  typedef RTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
  TreeType tree(data);

  TreeType* xmlTree;
  TreeType* textTree;
  TreeType* binaryTree;

  SerializePointerObjectAll(&tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, *xmlTree, *textTree, *binaryTree);

  // Check a few other things too.
  std::stack<TreeType*> stack, xmlStack, textStack, binaryStack;
  stack.push(&tree);
  xmlStack.push(xmlTree);
  textStack.push(textTree);
  binaryStack.push(binaryTree);
  while (!stack.empty())
  {
    // Check more things...
    TreeType* node = stack.top();
    TreeType* xmlNode = xmlStack.top();
    TreeType* textNode = textStack.top();
    TreeType* binaryNode = binaryStack.top();
    stack.pop();
    xmlStack.pop();
    textStack.pop();
    binaryStack.pop();

    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), xmlNode->MaxLeafSize());
    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), textNode->MaxLeafSize());
    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), binaryNode->MaxLeafSize());

    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), xmlNode->MinLeafSize());
    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), textNode->MinLeafSize());
    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), binaryNode->MinLeafSize());

    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), xmlNode->MaxNumChildren());
    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), textNode->MaxNumChildren());
    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), binaryNode->MaxNumChildren());

    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), xmlNode->MinNumChildren());
    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), textNode->MinNumChildren());
    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), binaryNode->MinNumChildren());
  }

  delete xmlTree;
  delete textTree;
  delete binaryTree;
}

BOOST_AUTO_TEST_CASE(RectangleTreeOverwriteTest)
{
  arma::mat data;
  data.randu(3, 1000);
  typedef RTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
  TreeType tree(data);

  arma::mat otherData;
  otherData.randu(5, 50);
  TreeType xmlTree(otherData);
  TreeType textTree(otherData);
  TreeType binaryTree(textTree);

  SerializeObjectAll(tree, xmlTree, textTree, binaryTree);

  CheckTrees(tree, xmlTree, textTree, binaryTree);

  // Check a few other things too.
  std::stack<TreeType*> stack, xmlStack, textStack, binaryStack;
  stack.push(&tree);
  xmlStack.push(&xmlTree);
  textStack.push(&textTree);
  binaryStack.push(&binaryTree);
  while (!stack.empty())
  {
    // Check more things...
    TreeType* node = stack.top();
    TreeType* xmlNode = xmlStack.top();
    TreeType* textNode = textStack.top();
    TreeType* binaryNode = binaryStack.top();
    stack.pop();
    xmlStack.pop();
    textStack.pop();
    binaryStack.pop();

    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), xmlNode->MaxLeafSize());
    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), textNode->MaxLeafSize());
    BOOST_REQUIRE_EQUAL(node->MaxLeafSize(), binaryNode->MaxLeafSize());

    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), xmlNode->MinLeafSize());
    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), textNode->MinLeafSize());
    BOOST_REQUIRE_EQUAL(node->MinLeafSize(), binaryNode->MinLeafSize());

    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), xmlNode->MaxNumChildren());
    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), textNode->MaxNumChildren());
    BOOST_REQUIRE_EQUAL(node->MaxNumChildren(), binaryNode->MaxNumChildren());

    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), xmlNode->MinNumChildren());
    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), textNode->MinNumChildren());
    BOOST_REQUIRE_EQUAL(node->MinNumChildren(), binaryNode->MinNumChildren());
  }
}

BOOST_AUTO_TEST_CASE(PerceptronTest)
{
  // Create a perceptron.  Train it randomly.  Then check that it hasn't
  // changed.
  arma::mat data;
  data.randu(3, 100);
  arma::Row<size_t> labels(100);
  for (size_t i = 0; i < labels.n_elem; ++i)
  {
    if (data(1, i) > 0.5)
      labels[i] = 0;
    else
      labels[i] = 1;
  }

  Perceptron<> p(data, labels, 2, 15);

  Perceptron<> pXml(2, 3), pText(2, 3), pBinary(2, 3);
  SerializeObjectAll(p, pXml, pText, pBinary);

  // Now check that things are the same.
  CheckMatrices(p.Weights(), pXml.Weights(), pText.Weights(),
      pBinary.Weights());
  CheckMatrices(p.Biases(), pXml.Biases(), pText.Biases(), pBinary.Biases());

  BOOST_REQUIRE_EQUAL(p.MaxIterations(), pXml.MaxIterations());
  BOOST_REQUIRE_EQUAL(p.MaxIterations(), pText.MaxIterations());
  BOOST_REQUIRE_EQUAL(p.MaxIterations(), pBinary.MaxIterations());
}

BOOST_AUTO_TEST_CASE(LogisticRegressionTest)
{
  arma::mat data;
  data.randu(3, 100);
  arma::Row<size_t> responses;
  responses.randu(100);

  LogisticRegression<> lr(data, responses, 0.5);

  LogisticRegression<> lrXml(data, responses + 3, 0.3);
  LogisticRegression<> lrText(data, responses + 1);
  LogisticRegression<> lrBinary(3, 0.0);

  SerializeObjectAll(lr, lrXml, lrText, lrBinary);

  CheckMatrices(lr.Parameters(), lrXml.Parameters(), lrText.Parameters(),
      lrBinary.Parameters());

  BOOST_REQUIRE_CLOSE(lr.Lambda(), lrXml.Lambda(), 1e-5);
  BOOST_REQUIRE_CLOSE(lr.Lambda(), lrText.Lambda(), 1e-5);
  BOOST_REQUIRE_CLOSE(lr.Lambda(), lrBinary.Lambda(), 1e-5);
}

BOOST_AUTO_TEST_CASE(AllkNNTest)
{
  using neighbor::AllkNN;
  arma::mat dataset = arma::randu<arma::mat>(5, 2000);

  AllkNN allknn(dataset, false, false);

  AllkNN knnXml, knnText, knnBinary;

  SerializeObjectAll(allknn, knnXml, knnText, knnBinary);

  // Now run nearest neighbor and make sure the results are the same.
  arma::mat querySet = arma::randu<arma::mat>(5, 1000);

  arma::mat distances, xmlDistances, textDistances, binaryDistances;
  arma::Mat<size_t> neighbors, xmlNeighbors, textNeighbors, binaryNeighbors;

  allknn.Search(querySet, 5, neighbors, distances);
  knnXml.Search(querySet, 5, xmlNeighbors, xmlDistances);
  knnText.Search(querySet, 5, textNeighbors, textDistances);
  knnBinary.Search(querySet, 5, binaryNeighbors, binaryDistances);

  CheckMatrices(distances, xmlDistances, textDistances, binaryDistances);
  CheckMatrices(neighbors, xmlNeighbors, textNeighbors, binaryNeighbors);
}

BOOST_AUTO_TEST_CASE(SoftmaxRegressionTest)
{
  using regression::SoftmaxRegression;

  arma::mat dataset = arma::randu<arma::mat>(5, 1000);
  arma::Row<size_t> labels(1000);
  for (size_t i = 0; i < 500; ++i)
    labels[i] = 0;
  for (size_t i = 500; i < 1000; ++i)
    labels[i] = 1;

  SoftmaxRegression<> sr(dataset, labels, 2);

  SoftmaxRegression<> srXml(dataset.n_rows, 2);
  SoftmaxRegression<> srText(dataset.n_rows, 2);
  SoftmaxRegression<> srBinary(dataset.n_rows, 2);

  SerializeObjectAll(sr, srXml, srText, srBinary);

  CheckMatrices(sr.Parameters(), srXml.Parameters(), srText.Parameters(),
      srBinary.Parameters());
}

BOOST_AUTO_TEST_CASE(DETTest)
{
  using det::DTree;

  // Create a density estimation tree on a random dataset.
  arma::mat dataset = arma::randu<arma::mat>(25, 5000);

  DTree tree(dataset);

  arma::mat otherDataset = arma::randu<arma::mat>(5, 100);
  DTree xmlTree, binaryTree, textTree(otherDataset);

  SerializeObjectAll(tree, xmlTree, binaryTree, textTree);

  std::stack<DTree*> stack, xmlStack, binaryStack, textStack;
  stack.push(&tree);
  xmlStack.push(&xmlTree);
  binaryStack.push(&binaryTree);
  textStack.push(&textTree);

  while (!stack.empty())
  {
    // Get the top node from the stack.
    DTree* node = stack.top();
    DTree* xmlNode = xmlStack.top();
    DTree* binaryNode = binaryStack.top();
    DTree* textNode = textStack.top();

    stack.pop();
    xmlStack.pop();
    binaryStack.pop();
    textStack.pop();

    // Check that all the members are the same.
    BOOST_REQUIRE_EQUAL(node->Start(), xmlNode->Start());
    BOOST_REQUIRE_EQUAL(node->Start(), binaryNode->Start());
    BOOST_REQUIRE_EQUAL(node->Start(), textNode->Start());

    BOOST_REQUIRE_EQUAL(node->End(), xmlNode->End());
    BOOST_REQUIRE_EQUAL(node->End(), binaryNode->End());
    BOOST_REQUIRE_EQUAL(node->End(), textNode->End());

    BOOST_REQUIRE_EQUAL(node->SplitDim(), xmlNode->SplitDim());
    BOOST_REQUIRE_EQUAL(node->SplitDim(), binaryNode->SplitDim());
    BOOST_REQUIRE_EQUAL(node->SplitDim(), textNode->SplitDim());

    if (std::abs(node->SplitValue()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->SplitValue(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->SplitValue(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->SplitValue(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->SplitValue(), xmlNode->SplitValue(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->SplitValue(), binaryNode->SplitValue(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->SplitValue(), textNode->SplitValue(), 1e-5);
    }

    if (std::abs(node->LogNegError()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->LogNegError(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->LogNegError(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->LogNegError(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->LogNegError(), xmlNode->LogNegError(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->LogNegError(), binaryNode->LogNegError(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->LogNegError(), textNode->LogNegError(), 1e-5);
    }

    if (std::abs(node->SubtreeLeavesLogNegError()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->SubtreeLeavesLogNegError(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->SubtreeLeavesLogNegError(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->SubtreeLeavesLogNegError(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->SubtreeLeavesLogNegError(),
          xmlNode->SubtreeLeavesLogNegError(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->SubtreeLeavesLogNegError(),
          binaryNode->SubtreeLeavesLogNegError(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->SubtreeLeavesLogNegError(),
          textNode->SubtreeLeavesLogNegError(), 1e-5);
    }

    BOOST_REQUIRE_EQUAL(node->SubtreeLeaves(), xmlNode->SubtreeLeaves());
    BOOST_REQUIRE_EQUAL(node->SubtreeLeaves(), binaryNode->SubtreeLeaves());
    BOOST_REQUIRE_EQUAL(node->SubtreeLeaves(), textNode->SubtreeLeaves());

    if (std::abs(node->Ratio()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->Ratio(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->Ratio(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->Ratio(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->Ratio(), xmlNode->Ratio(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->Ratio(), binaryNode->Ratio(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->Ratio(), textNode->Ratio(), 1e-5);
    }

    if (std::abs(node->LogVolume()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->LogVolume(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->LogVolume(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->LogVolume(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->LogVolume(), xmlNode->LogVolume(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->LogVolume(), binaryNode->LogVolume(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->LogVolume(), textNode->LogVolume(), 1e-5);
    }

    if (node->Left() == NULL)
    {
      BOOST_REQUIRE(xmlNode->Left() == NULL);
      BOOST_REQUIRE(binaryNode->Left() == NULL);
      BOOST_REQUIRE(textNode->Left() == NULL);
    }
    else
    {
      BOOST_REQUIRE(xmlNode->Left() != NULL);
      BOOST_REQUIRE(binaryNode->Left() != NULL);
      BOOST_REQUIRE(textNode->Left() != NULL);

      // Push children onto stack.
      stack.push(node->Left());
      xmlStack.push(xmlNode->Left());
      binaryStack.push(binaryNode->Left());
      textStack.push(textNode->Left());
    }

    if (node->Right() == NULL)
    {
      BOOST_REQUIRE(xmlNode->Right() == NULL);
      BOOST_REQUIRE(binaryNode->Right() == NULL);
      BOOST_REQUIRE(textNode->Right() == NULL);
    }
    else
    {
      BOOST_REQUIRE(xmlNode->Right() != NULL);
      BOOST_REQUIRE(binaryNode->Right() != NULL);
      BOOST_REQUIRE(textNode->Right() != NULL);

      // Push children onto stack.
      stack.push(node->Right());
      xmlStack.push(xmlNode->Right());
      binaryStack.push(binaryNode->Right());
      textStack.push(textNode->Right());
    }

    BOOST_REQUIRE_EQUAL(node->Root(), xmlNode->Root());
    BOOST_REQUIRE_EQUAL(node->Root(), binaryNode->Root());
    BOOST_REQUIRE_EQUAL(node->Root(), textNode->Root());

    if (std::abs(node->AlphaUpper()) < 1e-5)
    {
      BOOST_REQUIRE_SMALL(xmlNode->AlphaUpper(), 1e-5);
      BOOST_REQUIRE_SMALL(binaryNode->AlphaUpper(), 1e-5);
      BOOST_REQUIRE_SMALL(textNode->AlphaUpper(), 1e-5);
    }
    else
    {
      BOOST_REQUIRE_CLOSE(node->AlphaUpper(), xmlNode->AlphaUpper(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->AlphaUpper(), binaryNode->AlphaUpper(), 1e-5);
      BOOST_REQUIRE_CLOSE(node->AlphaUpper(), textNode->AlphaUpper(), 1e-5);
    }

    BOOST_REQUIRE_EQUAL(node->MaxVals().n_elem, xmlNode->MaxVals().n_elem);
    BOOST_REQUIRE_EQUAL(node->MaxVals().n_elem, binaryNode->MaxVals().n_elem);
    BOOST_REQUIRE_EQUAL(node->MaxVals().n_elem, textNode->MaxVals().n_elem);
    for (size_t i = 0; i < node->MaxVals().n_elem; ++i)
    {
      if (std::abs(node->MaxVals()[i]) < 1e-5)
      {
        BOOST_REQUIRE_SMALL(xmlNode->MaxVals()[i], 1e-5);
        BOOST_REQUIRE_SMALL(binaryNode->MaxVals()[i], 1e-5);
        BOOST_REQUIRE_SMALL(textNode->MaxVals()[i], 1e-5);
      }
      else
      {
        BOOST_REQUIRE_CLOSE(node->MaxVals()[i], xmlNode->MaxVals()[i], 1e-5);
        BOOST_REQUIRE_CLOSE(node->MaxVals()[i], binaryNode->MaxVals()[i], 1e-5);
        BOOST_REQUIRE_CLOSE(node->MaxVals()[i], textNode->MaxVals()[i], 1e-5);
      }
    }

    BOOST_REQUIRE_EQUAL(node->MinVals().n_elem, xmlNode->MinVals().n_elem);
    BOOST_REQUIRE_EQUAL(node->MinVals().n_elem, binaryNode->MinVals().n_elem);
    BOOST_REQUIRE_EQUAL(node->MinVals().n_elem, textNode->MinVals().n_elem);
    for (size_t i = 0; i < node->MinVals().n_elem; ++i)
    {
      if (std::abs(node->MinVals()[i]) < 1e-5)
      {
        BOOST_REQUIRE_SMALL(xmlNode->MinVals()[i], 1e-5);
        BOOST_REQUIRE_SMALL(binaryNode->MinVals()[i], 1e-5);
        BOOST_REQUIRE_SMALL(textNode->MinVals()[i], 1e-5);
      }
      else
      {
        BOOST_REQUIRE_CLOSE(node->MinVals()[i], xmlNode->MinVals()[i], 1e-5);
        BOOST_REQUIRE_CLOSE(node->MinVals()[i], binaryNode->MinVals()[i], 1e-5);
        BOOST_REQUIRE_CLOSE(node->MinVals()[i], textNode->MinVals()[i], 1e-5);
      }
    }
  }
}

BOOST_AUTO_TEST_CASE(NaiveBayesSerializationTest)
{
  // Train NBC randomly.  Make sure the model is the same after serializing and
  // re-loading.
  arma::mat dataset;
  dataset.randu(10, 500);
  arma::Row<size_t> labels(500);
  for (size_t i = 0; i < 500; ++i)
  {
    if (dataset(0, i) > 0.5)
      labels[i] = 0;
    else
      labels[i] = 1;
  }

  NaiveBayesClassifier<> nbc(dataset, labels, 2);

  // Initialize some empty Naive Bayes classifiers.
  NaiveBayesClassifier<> xmlNbc(0, 0), textNbc(0, 0), binaryNbc(0, 0);
  SerializeObjectAll(nbc, xmlNbc, textNbc, binaryNbc);

  BOOST_REQUIRE_EQUAL(nbc.Means().n_elem, xmlNbc.Means().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Means().n_elem, textNbc.Means().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Means().n_elem, binaryNbc.Means().n_elem);
  for (size_t i = 0; i < nbc.Means().n_elem; ++i)
  {
    BOOST_REQUIRE_CLOSE(nbc.Means()[i], xmlNbc.Means()[i], 1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Means()[i], textNbc.Means()[i], 1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Means()[i], binaryNbc.Means()[i], 1e-5);
  }

  BOOST_REQUIRE_EQUAL(nbc.Variances().n_elem, xmlNbc.Variances().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Variances().n_elem, textNbc.Variances().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Variances().n_elem, binaryNbc.Variances().n_elem);
  for (size_t i = 0; i < nbc.Variances().n_elem; ++i)
  {
    BOOST_REQUIRE_CLOSE(nbc.Variances()[i], xmlNbc.Variances()[i], 1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Variances()[i], textNbc.Variances()[i], 1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Variances()[i], binaryNbc.Variances()[i], 1e-5);
  }

  BOOST_REQUIRE_EQUAL(nbc.Probabilities().n_elem,
      xmlNbc.Probabilities().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Probabilities().n_elem,
      textNbc.Probabilities().n_elem);
  BOOST_REQUIRE_EQUAL(nbc.Probabilities().n_elem,
      binaryNbc.Probabilities().n_elem);
  for (size_t i = 0; i < nbc.Probabilities().n_elem; ++i)
  {
    BOOST_REQUIRE_CLOSE(nbc.Probabilities()[i], xmlNbc.Probabilities()[i],
        1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Probabilities()[i], textNbc.Probabilities()[i],
        1e-5);
    BOOST_REQUIRE_CLOSE(nbc.Probabilities()[i], binaryNbc.Probabilities()[i],
        1e-5);
  }
}

BOOST_AUTO_TEST_CASE(RASearchTest)
{
  using neighbor::AllkRANN;
  using neighbor::AllkNN;
  arma::mat dataset = arma::randu<arma::mat>(5, 200);
  arma::mat otherDataset = arma::randu<arma::mat>(5, 100);

  // Find nearest neighbors in the top 10, with accuracy 0.95.  So 95% of the
  // results we get (at least) should fall into the top 10 of the true nearest
  // neighbors.
  AllkRANN allkrann(dataset, false, false, 5, 0.95);

  AllkRANN krannXml(otherDataset, false, false);
  AllkRANN krannText(otherDataset, true, false);
  AllkRANN krannBinary(otherDataset, true, true);

  SerializeObjectAll(allkrann, krannXml, krannText, krannBinary);

  // Now run nearest neighbor and make sure the results are the same.
  arma::mat querySet = arma::randu<arma::mat>(5, 100);

  arma::mat distances, xmlDistances, textDistances, binaryDistances;
  arma::Mat<size_t> neighbors, xmlNeighbors, textNeighbors, binaryNeighbors;

  AllkNN allknn(dataset); // Exact search.
  allknn.Search(querySet, 10, neighbors, distances);
  krannXml.Search(querySet, 5, xmlNeighbors, xmlDistances);
  krannText.Search(querySet, 5, textNeighbors, textDistances);
  krannBinary.Search(querySet, 5, binaryNeighbors, binaryDistances);

  BOOST_REQUIRE_EQUAL(xmlNeighbors.n_rows, 5);
  BOOST_REQUIRE_EQUAL(xmlNeighbors.n_cols, 100);
  BOOST_REQUIRE_EQUAL(textNeighbors.n_rows, 5);
  BOOST_REQUIRE_EQUAL(textNeighbors.n_cols, 100);
  BOOST_REQUIRE_EQUAL(binaryNeighbors.n_rows, 5);
  BOOST_REQUIRE_EQUAL(binaryNeighbors.n_cols, 100);

  size_t xmlCorrect = 0;
  size_t textCorrect = 0;
  size_t binaryCorrect = 0;
  for (size_t i = 0; i < xmlNeighbors.n_cols; ++i)
  {
    // See how many are in the top 10.
    for (size_t j = 0; j < xmlNeighbors.n_rows; ++j)
    {
      for (size_t k = 0; k < neighbors.n_rows; ++k)
      {
        if (neighbors(k, i) == xmlNeighbors(j, i))
          xmlCorrect++;
        if (neighbors(k, i) == textNeighbors(j, i))
          textCorrect++;
        if (neighbors(k, i) == binaryNeighbors(j, i))
          binaryCorrect++;
      }
    }
  }

  // We need 95% of these to be correct.
  BOOST_REQUIRE_GT(xmlCorrect, 95 * 5);
  BOOST_REQUIRE_GT(binaryCorrect, 95 * 5);
  BOOST_REQUIRE_GT(textCorrect, 95 * 5);
}

/**
 * Test that an LSH model can be serialized and deserialized.
 */
BOOST_AUTO_TEST_CASE(LSHTest)
{
  // Since we still don't have good tests for LSH, basically what we're going to
  // do is serialize an LSH model, and make sure we can deserialize it and that
  // we still get results when we call Search().
  arma::mat referenceData = arma::randu<arma::mat>(10, 100);

  LSHSearch<> lsh(referenceData, 5, 10); // Arbitrary chosen parameters.

  LSHSearch<> xmlLsh;
  arma::mat textData = arma::randu<arma::mat>(5, 50);
  LSHSearch<> textLsh(textData, 4, 5);
  LSHSearch<> binaryLsh(referenceData, 15, 2);

  // Now serialize.
  SerializeObjectAll(lsh, xmlLsh, textLsh, binaryLsh);

  // Check what we can about the serialized objects.
  BOOST_REQUIRE_EQUAL(lsh.NumProjections(), xmlLsh.NumProjections());
  BOOST_REQUIRE_EQUAL(lsh.NumProjections(), textLsh.NumProjections());
  BOOST_REQUIRE_EQUAL(lsh.NumProjections(), binaryLsh.NumProjections());
  for (size_t i = 0; i < lsh.NumProjections(); ++i)
  {
    CheckMatrices(lsh.Projection(i), xmlLsh.Projection(i),
        textLsh.Projection(i), binaryLsh.Projection(i));
  }

  CheckMatrices(lsh.ReferenceSet(), xmlLsh.ReferenceSet(),
      textLsh.ReferenceSet(), binaryLsh.ReferenceSet());
  CheckMatrices(lsh.Offsets(), xmlLsh.Offsets(), textLsh.Offsets(),
      binaryLsh.Offsets());
  CheckMatrices(lsh.SecondHashWeights(), xmlLsh.SecondHashWeights(),
      textLsh.SecondHashWeights(), binaryLsh.SecondHashWeights());

  BOOST_REQUIRE_EQUAL(lsh.BucketSize(), xmlLsh.BucketSize());
  BOOST_REQUIRE_EQUAL(lsh.BucketSize(), textLsh.BucketSize());
  BOOST_REQUIRE_EQUAL(lsh.BucketSize(), binaryLsh.BucketSize());

  CheckMatrices(lsh.SecondHashTable(), xmlLsh.SecondHashTable(),
      textLsh.SecondHashTable(), binaryLsh.SecondHashTable());
}

// Make sure serialization works for the decision stump.
BOOST_AUTO_TEST_CASE(DecisionStumpTest)
{
  // Generate dataset.
  arma::mat trainingData = arma::randu<arma::mat>(4, 100);
  arma::Row<size_t> labels(100);
  for (size_t i = 0; i < 25; ++i)
    labels[i] = 0;
  for (size_t i = 25; i < 50; ++i)
    labels[i] = 3;
  for (size_t i = 50; i < 75; ++i)
    labels[i] = 1;
  for (size_t i = 75; i < 100; ++i)
    labels[i] = 2;

  DecisionStump<> ds(trainingData, labels, 4, 3);

  arma::mat otherData = arma::randu<arma::mat>(3, 100);
  arma::Row<size_t> otherLabels = arma::randu<arma::Row<size_t>>(100);
  DecisionStump<> xmlDs(otherData, otherLabels, 2, 3);

  DecisionStump<> textDs;
  DecisionStump<> binaryDs(trainingData, labels, 4, 10);

  SerializeObjectAll(ds, xmlDs, textDs, binaryDs);

  // Make sure that everything is the same about the new decision stumps.
  BOOST_REQUIRE_EQUAL(ds.SplitDimension(), xmlDs.SplitDimension());
  BOOST_REQUIRE_EQUAL(ds.SplitDimension(), textDs.SplitDimension());
  BOOST_REQUIRE_EQUAL(ds.SplitDimension(), binaryDs.SplitDimension());

  CheckMatrices(ds.Split(), xmlDs.Split(), textDs.Split(), binaryDs.Split());
  CheckMatrices(ds.BinLabels(), xmlDs.BinLabels(), textDs.BinLabels(),
      binaryDs.BinLabels());
}

// Make sure serialization works for LARS.
BOOST_AUTO_TEST_CASE(LARSTest)
{
  using namespace mlpack::regression;

  // Create a dataset.
  arma::mat X = arma::randn(75, 250);
  arma::vec beta = arma::randn(75, 1);
  arma::vec y = trans(X) * beta;

  LARS lars(true, 0.1, 0.1);
  arma::vec betaOpt;
  lars.Train(X, y, betaOpt);

  // Now, serialize.
  LARS xmlLars(false, 0.5, 0.0), binaryLars(true, 1.0, 0.0),
      textLars(false, 0.1, 0.1);

  // Train textLars.
  arma::mat textX = arma::randn(25, 150);
  arma::vec textBeta = arma::randn(25, 1);
  arma::vec textY = trans(textX) * textBeta;
  arma::vec textBetaOpt;
  textLars.Train(textX, textY, textBetaOpt);

  SerializeObjectAll(lars, xmlLars, binaryLars, textLars);

  // Now, check that predictions are the same.
  arma::vec pred, xmlPred, textPred, binaryPred;
  lars.Predict(X, pred);
  xmlLars.Predict(X, xmlPred);
  textLars.Predict(X, textPred);
  binaryLars.Predict(X, binaryPred);

  CheckMatrices(pred, xmlPred, textPred, binaryPred);
}

/**
 * Test serialization of the HoeffdingNumericSplit object after binning has
 * occured.
 */
BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitTest)
{
  using namespace mlpack::tree;

  HoeffdingNumericSplit<GiniImpurity> split(3);
  // Train until it bins.
  for (size_t i = 0; i < 200; ++i)
    split.Train(mlpack::math::Random(), mlpack::math::RandInt(3));

  HoeffdingNumericSplit<GiniImpurity> xmlSplit(5);
  HoeffdingNumericSplit<GiniImpurity> textSplit(7);
  for (size_t i = 0; i < 200; ++i)
    textSplit.Train(mlpack::math::Random() + 3, 0);
  HoeffdingNumericSplit<GiniImpurity> binarySplit(2);

  SerializeObjectAll(split, xmlSplit, textSplit, binarySplit);

  // Ensure that everything is the same.
  BOOST_REQUIRE_EQUAL(split.Bins(), xmlSplit.Bins());
  BOOST_REQUIRE_EQUAL(split.Bins(), textSplit.Bins());
  BOOST_REQUIRE_EQUAL(split.Bins(), binarySplit.Bins());

  double bestSplit, secondBestSplit;
  double baseBestSplit, baseSecondBestSplit;
  split.EvaluateFitnessFunction(baseBestSplit, baseSecondBestSplit);
  xmlSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  textSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  binarySplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  arma::Col<size_t> children, xmlChildren, textChildren, binaryChildren;
  NumericSplitInfo<double> splitInfo, xmlSplitInfo, textSplitInfo,
      binarySplitInfo;

  split.Split(children, splitInfo);
  xmlSplit.Split(xmlChildren, xmlSplitInfo);
  binarySplit.Split(binaryChildren, binarySplitInfo);
  textSplit.Split(textChildren, textSplitInfo);

  BOOST_REQUIRE_EQUAL(children.size(), xmlChildren.size());
  BOOST_REQUIRE_EQUAL(children.size(), textChildren.size());
  BOOST_REQUIRE_EQUAL(children.size(), binaryChildren.size());
  for (size_t i = 0; i < children.size(); ++i)
  {
    BOOST_REQUIRE_EQUAL(children[i], xmlChildren[i]);
    BOOST_REQUIRE_EQUAL(children[i], textChildren[i]);
    BOOST_REQUIRE_EQUAL(children[i], binaryChildren[i]);
  }

  // Random checks.
  for (size_t i = 0; i < 200; ++i)
  {
    const double random = mlpack::math::Random() * 1.5;
    BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(random),
                        xmlSplitInfo.CalculateDirection(random));
    BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(random),
                        textSplitInfo.CalculateDirection(random));
    BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(random),
                        binarySplitInfo.CalculateDirection(random));
  }
}

/**
 * Make sure serialization of the HoeffdingNumericSplit object before binning
 * occurs is successful.
 */
BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitBeforeBinningTest)
{
  using namespace mlpack::tree;

  HoeffdingNumericSplit<GiniImpurity> split(3);
  // Train but not until it bins.
  for (size_t i = 0; i < 50; ++i)
    split.Train(mlpack::math::Random(), mlpack::math::RandInt(3));

  HoeffdingNumericSplit<GiniImpurity> xmlSplit(5);
  HoeffdingNumericSplit<GiniImpurity> textSplit(7);
  for (size_t i = 0; i < 200; ++i)
    textSplit.Train(mlpack::math::Random() + 3, 0);
  HoeffdingNumericSplit<GiniImpurity> binarySplit(2);

  SerializeObjectAll(split, xmlSplit, textSplit, binarySplit);

  // Ensure that everything is the same.
  BOOST_REQUIRE_EQUAL(split.Bins(), xmlSplit.Bins());
  BOOST_REQUIRE_EQUAL(split.Bins(), textSplit.Bins());
  BOOST_REQUIRE_EQUAL(split.Bins(), binarySplit.Bins());

  double baseBestSplit, baseSecondBestSplit;
  double bestSplit, secondBestSplit;
  split.EvaluateFitnessFunction(baseBestSplit, baseSecondBestSplit);
  textSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);

  BOOST_REQUIRE_SMALL(baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(baseSecondBestSplit, 1e-5);

  BOOST_REQUIRE_SMALL(bestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-5);

  xmlSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_SMALL(bestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-5);

  binarySplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_SMALL(bestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-5);
}

/**
 * Make sure the HoeffdingCategoricalSplit object serializes correctly.
 */
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitTest)
{
  using namespace mlpack::tree;

  HoeffdingCategoricalSplit<GiniImpurity> split(10, 3);
  for (size_t i = 0; i < 50; ++i)
    split.Train(mlpack::math::RandInt(10), mlpack::math::RandInt(3));

  HoeffdingCategoricalSplit<GiniImpurity> xmlSplit(3, 7);
  HoeffdingCategoricalSplit<GiniImpurity> binarySplit(4, 11);
  HoeffdingCategoricalSplit<GiniImpurity> textSplit(2, 2);
  for (size_t i = 0; i < 10; ++i)
    textSplit.Train(mlpack::math::RandInt(2), mlpack::math::RandInt(2));

  SerializeObjectAll(split, xmlSplit, textSplit, binarySplit);

  BOOST_REQUIRE_EQUAL(split.MajorityClass(), xmlSplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), textSplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), binarySplit.MajorityClass());

  double bestSplit, secondBestSplit;
  double baseBestSplit, baseSecondBestSplit;
  split.EvaluateFitnessFunction(baseBestSplit, baseSecondBestSplit);
  xmlSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);

  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  textSplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  binarySplit.EvaluateFitnessFunction(bestSplit, secondBestSplit);
  BOOST_REQUIRE_CLOSE(bestSplit, baseBestSplit, 1e-5);
  BOOST_REQUIRE_SMALL(secondBestSplit, 1e-10);

  arma::Col<size_t> children, xmlChildren, textChildren, binaryChildren;
  CategoricalSplitInfo splitInfo(1); // I don't care about this.

  split.Split(children, splitInfo);
  xmlSplit.Split(xmlChildren, splitInfo);
  binarySplit.Split(binaryChildren, splitInfo);
  textSplit.Split(textChildren, splitInfo);

  BOOST_REQUIRE_EQUAL(children.size(), xmlChildren.size());
  BOOST_REQUIRE_EQUAL(children.size(), textChildren.size());
  BOOST_REQUIRE_EQUAL(children.size(), binaryChildren.size());
  for (size_t i = 0; i < children.size(); ++i)
  {
    BOOST_REQUIRE_EQUAL(children[i], xmlChildren[i]);
    BOOST_REQUIRE_EQUAL(children[i], textChildren[i]);
    BOOST_REQUIRE_EQUAL(children[i], binaryChildren[i]);
  }
}

/**
 * Make sure the HoeffdingTree object serializes correctly before a split has
 * occured.
 */
BOOST_AUTO_TEST_CASE(HoeffdingTreeBeforeSplitTest)
{
  data::DatasetInfo info(5);
  info.MapString("0", 2); // Dimension 1 is categorical.
  info.MapString("1", 2);
  HoeffdingTree<> split(info, 2, 0.99, 15000, 1);

  // Train for 2 samples.
  split.Train(arma::vec("0.3 0.4 1 0.6 0.7"), 0);
  split.Train(arma::vec("-0.3 0.0 0 0.7 0.8"), 1);

  data::DatasetInfo wrongInfo(3);
  wrongInfo.MapString("1", 1);
  HoeffdingTree<> xmlSplit(wrongInfo, 7, 0.1, 10, 1);

  // Force the binarySplit to split.
  data::DatasetInfo binaryInfo(2);
  binaryInfo.MapString("cat0", 0);
  binaryInfo.MapString("cat1", 0);
  binaryInfo.MapString("cat0", 1);

  HoeffdingTree<> binarySplit(info, 2, 0.95, 5000, 1);

  // Feed samples from each class.
  for (size_t i = 0; i < 500; ++i)
  {
    binarySplit.Train(arma::Col<size_t>("0 0"), 0);
    binarySplit.Train(arma::Col<size_t>("1 0"), 1);
  }

  HoeffdingTree<> textSplit(wrongInfo, 11, 0.75, 1000, 1);

  SerializeObjectAll(split, xmlSplit, textSplit, binarySplit);

  BOOST_REQUIRE_EQUAL(split.SplitDimension(), xmlSplit.SplitDimension());
  BOOST_REQUIRE_EQUAL(split.SplitDimension(), binarySplit.SplitDimension());
  BOOST_REQUIRE_EQUAL(split.SplitDimension(), textSplit.SplitDimension());

  BOOST_REQUIRE_EQUAL(split.MajorityClass(), xmlSplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), binarySplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), textSplit.MajorityClass());

  BOOST_REQUIRE_EQUAL(split.SplitCheck(), xmlSplit.SplitCheck());
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), binarySplit.SplitCheck());
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), textSplit.SplitCheck());
}

/**
 * Make sure the HoeffdingTree object serializes correctly after a split has
 * occurred.
 */
BOOST_AUTO_TEST_CASE(HoeffdingTreeAfterSplitTest)
{
  // Force the split to split.
  data::DatasetInfo info(2);
  info.MapString("cat0", 0);
  info.MapString("cat1", 0);
  info.MapString("cat0", 1);

  HoeffdingTree<> split(info, 2, 0.95, 5000, 1);

  // Feed samples from each class.
  for (size_t i = 0; i < 500; ++i)
  {
    split.Train(arma::Col<size_t>("0 0"), 0);
    split.Train(arma::Col<size_t>("1 0"), 1);
  }
  // Ensure a split has happened.
  BOOST_REQUIRE_NE(split.SplitDimension(), size_t(-1));

  data::DatasetInfo wrongInfo(3);
  wrongInfo.MapString("1", 1);
  HoeffdingTree<> xmlSplit(wrongInfo, 7, 0.1, 10, 1);

  data::DatasetInfo binaryInfo(5);
  binaryInfo.MapString("0", 2); // Dimension 2 is categorical.
  binaryInfo.MapString("1", 2);
  HoeffdingTree<> binarySplit(binaryInfo, 2, 0.99, 15000, 1);

  // Train for 2 samples.
  binarySplit.Train(arma::vec("0.3 0.4 1 0.6 0.7"), 0);
  binarySplit.Train(arma::vec("-0.3 0.0 0 0.7 0.8"), 1);

  HoeffdingTree<> textSplit(wrongInfo, 11, 0.75, 1000, 1);

  SerializeObjectAll(split, xmlSplit, textSplit, binarySplit);

  BOOST_REQUIRE_EQUAL(split.SplitDimension(), xmlSplit.SplitDimension());
  BOOST_REQUIRE_EQUAL(split.SplitDimension(), binarySplit.SplitDimension());
  BOOST_REQUIRE_EQUAL(split.SplitDimension(), textSplit.SplitDimension());

  // If splitting has already happened, then SplitCheck() should return 0.
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), 0);
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), xmlSplit.SplitCheck());
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), binarySplit.SplitCheck());
  BOOST_REQUIRE_EQUAL(split.SplitCheck(), textSplit.SplitCheck());

  BOOST_REQUIRE_EQUAL(split.MajorityClass(), xmlSplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), binarySplit.MajorityClass());
  BOOST_REQUIRE_EQUAL(split.MajorityClass(), textSplit.MajorityClass());

  BOOST_REQUIRE_EQUAL(split.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")),
      xmlSplit.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")));
  BOOST_REQUIRE_EQUAL(split.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")),
      binarySplit.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")));
  BOOST_REQUIRE_EQUAL(split.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")),
      textSplit.CalculateDirection(arma::vec("0.3 0.4 1 0.6 0.7")));
}

BOOST_AUTO_TEST_CASE(EmptyHoeffdingTreeTest)
{
  using namespace mlpack::tree;

  data::DatasetInfo info(6);
  HoeffdingTree<> tree(info, 2);
  HoeffdingTree<> xmlTree(info, 3);
  HoeffdingTree<> binaryTree(info, 4);
  HoeffdingTree<> textTree(info, 5);

  SerializeObjectAll(tree, xmlTree, binaryTree, textTree);

  BOOST_REQUIRE_EQUAL(tree.NumChildren(), 0);
  BOOST_REQUIRE_EQUAL(xmlTree.NumChildren(), 0);
  BOOST_REQUIRE_EQUAL(binaryTree.NumChildren(), 0);
  BOOST_REQUIRE_EQUAL(textTree.NumChildren(), 0);
}

/**
 * Build a Hoeffding tree, then save it and make sure other trees can classify
 * as effectively.
 */
BOOST_AUTO_TEST_CASE(HoeffdingTreeTest)
{
  using namespace mlpack::tree;

  arma::mat dataset(2, 400);
  arma::Row<size_t> labels(400);
  for (size_t i = 0; i < 200; ++i)
  {
    dataset(0, 2 * i) = mlpack::math::RandInt(4);
    dataset(1, 2 * i) = mlpack::math::RandInt(2);
    dataset(0, 2 * i + 1) = mlpack::math::RandInt(4);
    dataset(1, 2 * i + 1) = mlpack::math::RandInt(2) + 2;
    labels[2 * i] = 0;
    labels[2 * i + 1] = 1;
  }
  // Make the features categorical.
  data::DatasetInfo info(2);
  info.MapString("a", 0);
  info.MapString("b", 0);
  info.MapString("c", 0);
  info.MapString("d", 0);
  info.MapString("a", 1);
  info.MapString("b", 1);
  info.MapString("c", 1);
  info.MapString("d", 1);

  HoeffdingTree<> tree(dataset, info, labels, 2, false /* no batch mode */);

  data::DatasetInfo xmlInfo(1);
  HoeffdingTree<> xmlTree(xmlInfo, 1);
  data::DatasetInfo binaryInfo(5);
  HoeffdingTree<> binaryTree(binaryInfo, 6);
  data::DatasetInfo textInfo(7);
  HoeffdingTree<> textTree(textInfo, 100);

  SerializeObjectAll(tree, xmlTree, textTree, binaryTree);

  BOOST_REQUIRE_EQUAL(tree.NumChildren(), xmlTree.NumChildren());
  BOOST_REQUIRE_EQUAL(tree.NumChildren(), textTree.NumChildren());
  BOOST_REQUIRE_EQUAL(tree.NumChildren(), binaryTree.NumChildren());

  BOOST_REQUIRE_EQUAL(tree.SplitDimension(), xmlTree.SplitDimension());
  BOOST_REQUIRE_EQUAL(tree.SplitDimension(), textTree.SplitDimension());
  BOOST_REQUIRE_EQUAL(tree.SplitDimension(), binaryTree.SplitDimension());

  for (size_t i = 0; i < tree.NumChildren(); ++i)
  {
    BOOST_REQUIRE_EQUAL(tree.Child(i).NumChildren(), 0);
    BOOST_REQUIRE_EQUAL(xmlTree.Child(i).NumChildren(), 0);
    BOOST_REQUIRE_EQUAL(binaryTree.Child(i).NumChildren(), 0);
    BOOST_REQUIRE_EQUAL(textTree.Child(i).NumChildren(), 0);

    BOOST_REQUIRE_EQUAL(tree.Child(i).SplitDimension(),
        xmlTree.Child(i).SplitDimension());
    BOOST_REQUIRE_EQUAL(tree.Child(i).SplitDimension(),
        textTree.Child(i).SplitDimension());
    BOOST_REQUIRE_EQUAL(tree.Child(i).SplitDimension(),
        binaryTree.Child(i).SplitDimension());
  }
}

BOOST_AUTO_TEST_SUITE_END();

max_stars_repo_name: abhinvgpta/mlpack

max_issues_repo_name: decltypeme/mlpack

max_forks_repo_name: decltypeme/mlpack


text:
#include <iostream>
#include <string>
#include <algorithm>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

int main(int argc, const char *argv[])
{
  // Check provided parameters
  if (argc != 2) {
    std::cerr << "Error. Bad number of parameters" << std::endl;
    std::cerr << "Usage: " << argv[0] << " <port>" << std::endl;
    exit(-1);
  }
  // Get the port from the parameters
  uint16_t port = std::stoul(argv[1]);

  // Error to not throw exception
  boost::system::error_code not_throw;

  // Socket and acceptor
  boost::asio::io_service service;
  tcp::acceptor acceptor(service, tcp::endpoint(tcp::v4(), port));
  tcp::socket socket(service);
  acceptor.accept(socket, not_throw);
  if (not_throw) {
    std::cerr << "Error when binding the port in the socket" << std::endl;
    return 1;
  }

  // Read a message
  size_t size;
  char buf[512];
  std::ostringstream oss;
  boost::system::error_code error = boost::asio::error::eof;
  do {
    size = socket.read_some(boost::asio::buffer(buf), error);
    oss << std::string(buf, size);
  } while(error && error != boost::asio::error::eof);

  // Reverse the received message
  std::string original = oss.str();
  std::reverse(std::begin(original), std::end(original));

  // Write the reversed message
  socket.write_some(boost::asio::buffer(original), not_throw);
  if (not_throw) {
    std::cerr << "Error sending(" << not_throw.value() << "): " << not_throw.message() << std::endl;
    return 1;
  }

  // Close socket
  socket.close();

  return 0;
}

max_stars_repo_name: maitesin/blog

max_issues_repo_name: maitesin/blog

max_forks_repo_name: maitesin/blog


text:
//          Copyright Oliver Kowalke 2016.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_FIBERS_SPINLOCK_TTAS_H
#define BOOST_FIBERS_SPINLOCK_TTAS_H

#include <atomic>
#include <chrono>
#include <cmath>
#include <random>
#include <thread>

#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/cpu_relax.hpp>
#include <boost/fiber/detail/spinlock_status.hpp>

// based on informations from:
// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors

namespace boost {
namespace fibers {
namespace detail {

class spinlock_ttas {
private:
    template< typename FBSplk >
    friend class spinlock_rtm;

    std::atomic< spinlock_status >              state_{ spinlock_status::unlocked };

public:
    spinlock_ttas() = default;

    spinlock_ttas( spinlock_ttas const&) = delete;
    spinlock_ttas & operator=( spinlock_ttas const&) = delete;

    void lock() noexcept {
        static thread_local std::minstd_rand generator{ std::random_device{}() };
        std::size_t collisions = 0 ;
        for (;;) {
            // avoid using multiple pause instructions for a delay of a specific cycle count
            // the delay of cpu_relax() (pause on Intel) depends on the processor family
            // the cycle count can not guaranteed from one system to the next
            // -> check the shared variable 'state_' in between each cpu_relax() to prevent
            //    unnecessarily long delays on some systems
            std::size_t retries = 0;
            // test shared variable 'status_'
            // first access to 'state_' -> chache miss
            // sucessive acccess to 'state_' -> cache hit
            // if 'state_' was released by other fiber
            // cached 'state_' is invalidated -> cache miss
            while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
                if ( BOOST_FIBERS_SPIN_BEFORE_SLEEP0 > retries) {
                    ++retries;
                    // give CPU a hint that this thread is in a "spin-wait" loop
                    // delays the next instruction's execution for a finite period of time (depends on processor family)
                    // the CPU is not under demand, parts of the pipeline are no longer being used
                    // -> reduces the power consumed by the CPU
                    // -> prevent pipeline stalls
                    cpu_relax();
                } else if ( BOOST_FIBERS_SPIN_BEFORE_YIELD > retries) {
                    // std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
                    // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
                    // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
                    // if and only if a thread of equal or greater priority is ready to run
                    static constexpr std::chrono::microseconds us0{ 0 };
                    std::this_thread::sleep_for( us0);
                } else {
                    // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
                    // but only to another thread on the same processor
                    // instead of constant checking, a thread only checks if no other useful work is pending
                    std::this_thread::yield();
                }
#else
                std::this_thread::yield();
#endif
            }
            // test-and-set shared variable 'status_'
            // everytime 'status_' is signaled over the bus, even if the test failes
            if ( spinlock_status::locked == state_.exchange( spinlock_status::locked, std::memory_order_acquire) ) {
                // spinlock now contended
                // utilize 'Binary Exponential Backoff' algorithm
                // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
                std::uniform_int_distribution< std::size_t > distribution{
                    0, static_cast< std::size_t >( 1) << (std::min)(collisions, static_cast< std::size_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
                const std::size_t z = distribution( generator);
                ++collisions;
                for ( std::size_t i = 0; i < z; ++i) {
                    // -> reduces the power consumed by the CPU
                    // -> prevent pipeline stalls
                    cpu_relax();
                }
            } else {
                // success, thread has acquired the lock
                break;
            }
        }
    }

    bool try_lock() noexcept {
        return spinlock_status::unlocked == state_.exchange( spinlock_status::locked, std::memory_order_acquire);
    }

    void unlock() noexcept {
        state_.store( spinlock_status::unlocked, std::memory_order_release);
    }
};

}}}

#endif // BOOST_FIBERS_SPINLOCK_TTAS_H

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
/*-----------------------------------------------------------------------------+
Copyright (c) 2008-2009: Joachim Faulhaber
+------------------------------------------------------------------------------+
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENCE.txt or copy at
           http://www.boost.org/LICENSE_1_0.txt)
+-----------------------------------------------------------------------------*/
#ifndef BOOST_ICL_DETAIL_DISABLE_TEST_WARNINGS_HPP_JOFA_101031
#define BOOST_ICL_DETAIL_DISABLE_TEST_WARNINGS_HPP_JOFA_101031

#include <boost/icl/detail/boost_config.hpp>
#include <boost/detail/workaround.hpp>

#ifdef BOOST_MSVC             // These warnings are disabled permanently for tests.
#pragma warning(disable:4996) // Function call with parameters that may be unsafe
#pragma warning(disable:4503) // decorated name length exceeded, name was truncated
#pragma warning(disable:4702) // unreachable code
#endif

#endif // BOOST_ICL_DETAIL_DISABLE_TEST_WARNINGS_HPP_JOFA_101031

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
//==============================================================================
//         Copyright 2003 - 2011 LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//         Copyright 2012 - 2014 MetaScale SAS
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_IEEE_FUNCTIONS_SCALAR_PREDECESSOR_HPP_INCLUDED
#define BOOST_SIMD_IEEE_FUNCTIONS_SCALAR_PREDECESSOR_HPP_INCLUDED

#include <boost/simd/ieee/functions/predecessor.hpp>
#include <boost/simd/include/functions/scalar/bitfloating.hpp>
#include <boost/simd/include/functions/scalar/bitinteger.hpp>
#include <boost/simd/include/functions/scalar/minusone.hpp>
#include <boost/simd/include/functions/scalar/subs.hpp>
#include <boost/simd/include/functions/scalar/is_nan.hpp>
#include <boost/simd/include/functions/scalar/is_gez.hpp>
#include <boost/simd/include/constants/valmin.hpp>
#include <boost/assert.hpp>
#include <boost/dispatch/attributes.hpp>

namespace boost { namespace simd { namespace ext
{
  BOOST_DISPATCH_IMPLEMENT          ( predecessor_, tag::cpu_
                                    , (A0)
                                    , (scalar_< arithmetic_<A0> >)
                                      (scalar_< integer_<A0> >)
                                    )
  {
    typedef A0 result_type;
    BOOST_FORCEINLINE BOOST_SIMD_FUNCTOR_CALL_REPEAT(2)
    {
      BOOST_ASSERT_MSG(is_gez(a1), "predecessor rank must be non negative");
      if (Valmin<A0>()+a1 > a0) return Valmin<A0>();
      return a0-a1;
    }
  };

  BOOST_DISPATCH_IMPLEMENT          ( predecessor_, tag::cpu_
                                    , (A0)
                                    , (scalar_< arithmetic_<A0> >)
                                    )
  {
    typedef A0 result_type;
    BOOST_FORCEINLINE BOOST_SIMD_FUNCTOR_CALL(1)
    {
      return minusone(a0);
    }
  };

  BOOST_DISPATCH_IMPLEMENT          ( predecessor_, tag::cpu_
                                    , (A0)(A1)
                                    , (scalar_< floating_<A0> >)
                                      (scalar_< integer_<A1> >)
                                    )
  {

    typedef A0 result_type;

    BOOST_FORCEINLINE BOOST_SIMD_FUNCTOR_CALL(2)
    {
      typedef typename dispatch::meta::as_integer<A0>::type itype;
      BOOST_ASSERT_MSG(is_gez(a1), "predecessor rank must be non negative");
      if (is_nan(a0)) return a0;
      return bitfloating(subs(bitinteger(a0), itype(a1)));
    }
  };

  BOOST_DISPATCH_IMPLEMENT          ( predecessor_, tag::cpu_
                                    , (A0)
                                    , (scalar_< floating_<A0> >)
                                    )
  {

    typedef A0 result_type;

    BOOST_FORCEINLINE BOOST_SIMD_FUNCTOR_CALL(1)
    {
      if (is_nan(a0)) return a0;
      return bitfloating(minusone(bitinteger(a0)));
    }
  };
} } }

#endif