#include <iostream>
#include <fstream>
#include <string>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

#include <SurfaceBasedRegistration.hpp>

#include <Util.hpp>

int main(int argc, char** argv) {
    try {
        std::string appName = boost::filesystem::basename(argv[0]);

        std::string data1;
        std::string data2;
        std::string out;

        std::string init_file;

        namespace opts = boost::program_options;
        opts::options_description desc("Options");
        desc.add_options()
                ("help", "Print help message")
                ("data1", opts::value<std::string> (&data1)->required(), "First point cloud filename.")
                ("data2", opts::value<std::string> (&data2)->required(), "Second point cloud filename.")
                ("out", opts::value<std::string> (&out), "Output filename.")
                ("init_file", opts::value<std::string> (&init_file), "Filename for transformation initialisation matrix (4x4).")
        ;

        opts::positional_options_description positionalOptions;

        opts::variables_map vm;

        try {
            opts::store(opts::command_line_parser(argc, argv).options(desc)
                            .positional(positionalOptions).run(),
                        vm);
            if(vm.count("help")) {
                std::cout << "Program description." << std::endl;
                return 0;
            }

            opts::notify(vm);
        } catch(opts::required_option& e) {
            std::cerr << "ERROR: " << e.what() << std::endl << std::endl;

            return 1;
        } catch(boost::program_options::error& e) {
            std::cerr << "ERROR: " << e.what() << std::endl << std::endl;

            return 1;
        }

        if(vm.count("data1")) {
            std::cout << "data1 was " << vm["data1"].as<std::string>() << std::endl;
        }

        if(vm.count("data2")) {
            std::cout << "data2 was " << vm["data2"].as<std::string>() << std::endl;
        }

        if(vm.count("out")) {
            std::cout << "out was " << vm["out"].as<std::string>() << std::endl;
        }

        Eigen::Matrix4d init_matrix;
        if(vm.count("init_file")) {
            std::cout << "init_file was " << vm["init_file"].as<std::string>() << std::endl;
            init_matrix = load_transform_from_file(init_file);
            std::cout << "Transform initialised as " << std::endl << init_matrix << std::endl;
        }

        Eigen::MatrixXd pointcloud1;
        Eigen::MatrixXd pointcloud2;

        auto cloud1 = load_pointcloud_from_file(data1);
        auto cloud2 = load_pointcloud_from_file(data2);

        Eigen::Matrix4d transform;
        if(vm.count("init_file")) {
            transform = register_surfaces(cloud1, cloud2, init_matrix.inverse());
        } else {
            transform = register_surfaces(cloud1, cloud2);
        }

        if(vm.count("out")) {
            write_matrix_to_file(transform.inverse(), out);
        }

        std::cout << "Estimated transform was " << std::endl << transform.inverse() << std::endl;
    } catch(std::exception& e) {
        std::cerr << "Unhandled Exception reached the top of main: "
                  << e.what() << ", application will now exit" << std::endl;
        return 2;
    }
    return 0;
}


#include <iostream>
#include <boost/cstdint.hpp>
#include <CGAL/assertions.h>

int main()
{
  std::cout << "Verifying the sizes of boost::[u]int{8,16,32,64}_t"
            << std::endl;

  CGAL_static_assertion(sizeof(boost::int8_t)  == 1);
  CGAL_static_assertion(sizeof(boost::int16_t) == 2);
  CGAL_static_assertion(sizeof(boost::int32_t) == 4);
#ifndef BOOST_NO_INT64_T
  CGAL_static_assertion(sizeof(boost::int64_t) == 8);
#endif

  CGAL_static_assertion(sizeof(boost::uint8_t)  == 1);
  CGAL_static_assertion(sizeof(boost::uint16_t) == 2);
  CGAL_static_assertion(sizeof(boost::uint32_t) == 4);
#ifndef BOOST_NO_INT64_T
  CGAL_static_assertion(sizeof(boost::uint64_t) == 8);
#endif

  return 0;
}


// easylazy
//
// Copyright iorate 2019.
// 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)

#include <string>
#include <vector>
#include <boost/core/lightweight_test.hpp>
#include "../easylazy.hpp"

using namespace easylazy;

int main() {
    std::vector<int> v{1, 2, 3};
    list<int_> xs1(v);
    BOOST_TEST(xs1.get_as<std::vector<int>>() == v);
    list<int_> xs2{1, 2, 3};
    BOOST_TEST(xs2.get_as<std::vector<int>>() == v);
    list<int_> xs3(cons(1_d, cons(2_d, cons(3_d, nil<int_>()))));
    BOOST_TEST(xs3.get_as<std::vector<int>>() == v);

    string s = "hello"_s;
    BOOST_TEST(s.get_as<std::string>() == "hello");

    BOOST_TEST((list<int_>{1, 2}[1_d].get()) == 2);
    BOOST_TEST_THROWS((list<int_>{1, 2}[2_d].get()), std::out_of_range);

    BOOST_TEST((nil<int_>() < nil<int_>()).get() == false);
    BOOST_TEST((nil<int_>() < list<int_>{1, 2}).get() == true);
    BOOST_TEST((list<int_>{1, 2} > list<int_>{1}).get() == true);
    BOOST_TEST((list<int_>{1, 2} > list<int_>{2}).get() == false);
    BOOST_TEST((list<int_>{1, 1} <= list<int_>{1, 2}).get() == true);
    BOOST_TEST((list<int_>{1, 2} <= list<int_>{1, 2}).get() == true);
    BOOST_TEST((list<int_>{1, 2} >= list<int_>{1, 3}).get() == false);
    BOOST_TEST((list<int_>{1, 2} >= list<int_>{1, 2, 3}).get() == false);

    BOOST_TEST((nil<int_>() == nil<int_>()).get() == true);
    BOOST_TEST((nil<int_>() == list<int_>{1, 2}).get() == false);
    BOOST_TEST((list<int_>{1} == list<int_>{1, 2}).get() == false);
    BOOST_TEST((list<int_>{1, 2} != list<int_>{1, 2}).get() == false);
    BOOST_TEST((list<int_>{1, 2} != list<int_>{1, 3}).get() == true);

    BOOST_TEST(
        map(EASYLAZY_FUNCTION(int_ x) { return x * 2_d; }, list<int_>{1, 2})
            == (list<int_>{2, 4})
    );

    BOOST_TEST(
        append(list<int_>{1, 2}, list<int_>{3, 4})
            == (list<int_>{1, 2, 3, 4})
    );

    BOOST_TEST(
        filter(EASYLAZY_FUNCTION(int_ x) { return x % 2_d == 0_d; }, list<int_>{1, 2, 3, 4})
            == (list<int_>{2, 4})
    );

    BOOST_TEST(head(list<int_>{1, 2}) == 1_d);
    BOOST_TEST_THROWS(head(nil<int_>()).get(), std::invalid_argument);

    BOOST_TEST(last(list<int_>{1, 2}) == 2_d);
    BOOST_TEST_THROWS(last(nil<int_>()).get(), std::invalid_argument);

    BOOST_TEST(tail(list<int_>{1, 2}) == list<int_>{2});
    BOOST_TEST_THROWS(tail(nil<int_>()).get(), std::invalid_argument);

    BOOST_TEST(init(list<int_>{1, 2}) == list<int_>{1});
    BOOST_TEST_THROWS(init(nil<int_>()).get(), std::invalid_argument);

    BOOST_TEST(!null(list<int_>{1, 2}));
    BOOST_TEST(null(nil<int_>()));

    BOOST_TEST(length(list<int_>{1, 2}) == 2_d);
    BOOST_TEST(length(nil<int_>()) == 0_d);

    BOOST_TEST(reverse(list<int_>{1, 2}) == (list<int_>{2, 1}));

    return boost::report_errors();
}


/*
@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_TEST_LAWS_INTEGRAL_DOMAIN_HPP
#define BOOST_HANA_TEST_LAWS_INTEGRAL_DOMAIN_HPP

#include <boost/hana/assert.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/comparable.hpp>
#include <boost/hana/core/models.hpp>
#include <boost/hana/core/operators.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/integral_domain.hpp>

#include <laws/base.hpp>

namespace boost { namespace hana { namespace test {
    template <typename D, typename = when<true>>
    struct TestIntegralDomain : TestIntegralDomain<D, laws> {
        using TestIntegralDomain<D, laws>::TestIntegralDomain;
    };

    template <typename D>
    struct TestIntegralDomain<D, laws> {
        static_assert(_models<IntegralDomain, D>{}, "");

        template <typename Xs>
        TestIntegralDomain(Xs xs) {
            foreach3(xs, [](auto a, auto b, auto k) {

                // commutativity
                BOOST_HANA_CHECK(hana::equal(
                    hana::mult(a, b),
                    hana::mult(b, a)
                ));

                only_when_(hana::not_equal(b, zero<D>()), [=](auto _) {
                    auto b_ = _(b);
                    BOOST_HANA_CHECK(hana::equal(
                        hana::plus(
                            hana::mult(hana::quot(a, b_), b_),
                            hana::rem(a, b_)
                        ),
                        a
                    ));

                    BOOST_HANA_CHECK(hana::equal(
                        hana::rem(zero<D>(), b_),
                        zero<D>()
                    ));

                    // operators
                    only_when_(bool_<has_operator<D, decltype(rem)>{}>, [=](auto _) {
                        BOOST_HANA_CHECK(hana::equal(
                            hana::rem(a, _(b)),
                            _(a) % _(b)
                        ));
                    });

                    only_when_(bool_<has_operator<D, decltype(quot)>{}>, [=](auto _) {
                        BOOST_HANA_CHECK(hana::equal(
                            hana::quot(a, _(b)),
                            _(a) / _(b)
                        ));
                    });
                });

            });
        }
    };

    template <typename C>
    struct TestIntegralDomain<C, when<_models<Constant, C>{}>>
        : TestIntegralDomain<C, laws>
    {
        template <typename Xs>
        TestIntegralDomain(Xs xs) : TestIntegralDomain<C, laws>{xs} {
            foreach2(xs, [](auto x, auto y) {
                hana::eval_if(hana::equal(zero<C>(), y), [](auto){}, [=](auto _) {
                    auto y_ = _(y);

                    BOOST_HANA_CHECK(hana::equal(
                        hana::quot(hana::value(x), hana::value(y_)),
                        hana::value(hana::quot(x, y_))
                    ));

                    BOOST_HANA_CHECK(hana::equal(
                        hana::rem(hana::value(x), hana::value(y_)),
                        hana::value(hana::rem(x, y_))
                    ));

                });
            });
        }
    };
}}} // end namespace boost::hana::test

#endif // !BOOST_HANA_TEST_LAWS_INTEGRAL_DOMAIN_HPP


//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_SBITS_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_SBITS_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!

    @ingroup group-ieee
    Function object implementing sbits capabilities

    Returns the signed integer value which has the bit pattern of the input

    @par Semantic:

    For every parameter @c x of type @c T

    @code
    auto r = sbits(x);
    @endcode

    is similar to:

    @code
    auto r = bitwise_cast<as_integer_t<T,signed>>(x);
    @endcode

  **/
  IntegerValue sbits(Value const & v0);
} }
#endif

#include <boost/simd/function/scalar/sbits.hpp>
#include <boost/simd/function/simd/sbits.hpp>

#endif


/*
 * Copyright 2012, 2013 Matthew Harvey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef GUARD_decimal_hpp_0809249049429432
#define GUARD_decimal_hpp_0809249049429432

/** @file
 */

#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <algorithm>
#include <cctype>
#include <cstdlib>  // for abs
#include <cmath>
#include <istream>
#include <locale>
#include <memory>  // for allocator
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>

namespace jewel
{

/**
 * @brief A floating point decimal number class, with a somewhat limited
 * range, suited to use in accounting and financial applications.
 *
 * Each number is represented as an integer (of jewel::Decimal::int_type), and a
 * number of decimal places (of jewel::Decimal::places_type).
 *
 * The number of decimal places can be changed at runtime. As such this is a
 * floating rather than fixed point arithmetic type. However the range of
 * magnitudes is quite restricted compared to e.g. \e double.
 *
 * There are two concepts of precision for this Decimal class. The
 * total precision of a Decimal is the total number of
 * decimal digits, to either the left or the right of the decimal point,
 * stored in the instance. The fractional precision is the number of
 * digits stored to the right of the decimal point, i.e. the number of
 * digits in the fractional part.
 *
 * The maximum total precision of any given Decimal is equal to the number
 * of decimal digits in the largest possible Decimal. This
 * number is implementation-dependent, and is the number returned by
 * Decimal::maximum_precision(). Regardless of any of the behaviour
 * outlined below, the total precision of a Decimal will never exceed this
 * level. Note we cannot end up with a number that has more than this many
 * digits in its whole part, even if all but one of these digits are zero.
 * This significantly limits the range of this Decimal class compared to
 * typical floating point implementations.
 *
 * A single leading zero to the left of the decimal point
 * does not count towards the total precision of the Decimal.
 *
 * When a Decimal is constructed from a string, all digits of
 * precision that are implied by that string are retained in the Decimal
 * that is thereby constructed - regardless of whether some of these digits
 * are trailing fractional zeroes. For example, \c Decimal("0.2400")
 * will create a Decimal with 4 digits of total precision, and 4 digits of
 * fractional precision. If a Decimal cannot be created that would hold the
 * number of digits of precision implied by string, then an exception is
 * thrown.
 *
 * Multiplication and division behave slightly differently to addition and
 * subtraction. Trailing fractional zeroes in the result of these operations
 * are always "culled", even if this
 * would reduce the fractional precision of the result below that of either of
 * the operands. However, as with addition and subtraction, only fractional
 * zeroes are culled, and never whole digits.
 *
 * Apart from the above requirements, Decimals will store as many digits of
 * precision as possible. So "1/3" will result in "0.333...." with as many
 * trailing '3's as are permitted by the implementation.
 *
 * @todo LOW PRIORITY
 * Multiplication and division throw exceptions in some cases where
 * they should be able to calculate an answer. I have documented these
 * behaviours in the API docs. I don't believe this is a \e very serious
 * problem, as the behaviour is well documented and exceptions are thrown
 * rather than silent failure occurring. However, it is limiting
 * for certain use cases, and it makes for a messy API.
 * I should be able to get around this, and also
 * simplify my implementation of both division and multiplication, by
 * using boost::int32_t for int_type, while overflowing into boost::int64_t
 * within the implementation of these functions where required. The functions
 * will then only throw if the final value of m_intval cannot be fit into
 * boost::int32_t. The only problem then is that int_type is limited to
 * 32 bits. I'm not sure whether this is acceptable for e.g. an accounting
 * application. I think it is probably better to retain the current
 * "messy" situation until there's a clear need to reimplement things
 * in light of actual use cases.
 *
 * @todo LOW PRIORITY
 * Make it work as expected with standard library stream precision
 * manipulators and formatting. Create a function that takes a string
 * representation of a number, and the set of all the formatting flags
 * of an ostream (or a basic_ostream<>?), and use
 * those flags to format the string in accordance with those flags.
 * I should probably define this in a separate file. Note this is different
 * from the internationalization task which is separately noted.
 *
 * @todo MEDIUM PRIORITY
 * Internationalized output is working using the std::numpunct facilities.
 * But it doesn't support Boost.Locale. If the client uses Boost.Locale
 * instead of the standard library facilities, Decimal will
 * not do any formatting. Considering that
 * Boost.Locale \e seems to be necessary to get things working on Windows
 * properly, do I want to provide support for Boost.Locale in
 * jewel::Decimal?
 *
 * @todo MEDIUM PRIORITY
 * Support internationalization of input.
 *
 * @todo LOW PRIORITY
 * Division now incorporates rounding but: (a) it is a bit inefficient;
 * and (b) it contains a "hard-wired" behaviour of rounding up at 5, while not
 * actually referring to the Decimal::s_rounding_threshold constant to achieve
 * this. This is a kind of code repetition and so is bad.
 */
class Decimal
{
public:

    /** The type of the underlying integer representation of the
     * Decimal number.
     */
    typedef long long int_type;

    /** The type of the integer representation of the number of
     * decimal places (scale).
     */
    typedef unsigned char places_type;

    // Output
    template <typename charT, typename traits>
    friend
    std::basic_ostream<charT, traits>&
    operator<<(std::basic_ostream<charT, traits>&, Decimal const&);

    // Rounding
    friend Decimal round
    (   Decimal const& x,
        Decimal::places_type decimal_places
    );

    /** Unary minus
     *
     * See separate documentation for this function.
     */
    friend Decimal operator-(Decimal const& d);

    /**
     * Initializes the Decimal to 0, with 0 decimal places.
     *
     * Exception safety: nothrow guarantee.
     */
    Decimal();

    /**
     * Constructs a Decimal with an underlying integer of
     * p_intval and with p_places decimal places to the right
     * of the spot.
     *
     * @exception DecimalRangeException thrown if p_places
     * exceeds the value returned by Decimal::maximum_precision().
     *
     * Exception safety: strong guarantee.
     */
    Decimal(int_type m_intval, places_type p_places);

    /** Constructs a Decimal from a string.
     *
     * @param str is the string representation of a Decimal number. Must
     * be either a std::string const& or a
     * std::wstring const&, or else compilation will fail.
     *
     * Currently str must be a non-empty series of digits
     * between 0 and 9 inclusive, possibly preceded by a minus
     * sign, possibly followed by a decimal point character, possibly
     * followed by further digits between 0 and 9 inclusive. There must be
     * at least one digit in the string. The spot character is
     * determined by the current global \e std::locale (whatever \e std::locale
     * is created by the default constructor for \e std::locale). It could be
     * be ".", "," or some other character - whatever represents a
     * decimal point in that locale.
     *
     * Assuming "." for the global locale's decimal point, the following are
     * examples of accepted strings: "10", "0.0012", "-1.3", ".234".
     *
     * Assuming a "." for the global locale's decimal point,
     * the following are examples of non-accepted strings: "10e2",
     * "12312.234134341.23424", "1,000".
     *
     * @exception DecimalFromStringException is thrown if:\n
     *   an empty string is passed to \c str; or\n
     *   non-digit characters (other than '-' and the decimal point, at the
     *   appropriate point) are included in the string.
     *
     * @exception DecimalRangeException is thrown if \c str is otherwise
     *   valid, but
     *   the position of the decimal point implies a number of decimal places
     *   greater than the value returned by Decimal::maximum_precision().
     *
     * @exception DecimalRangeException also thrown if the implied Decimal
     *   number would be required to exceed the maximum of the underlying
     *   integral representation.
     *
     * @exception std::bad_alloc may be thrown - but this is unlikely - since
     * the implementation of this function involves the construction of a
     * std::string.
     *
     * Trailing zeroes to the right of the decimal point in the passed string
     * influence the number of digits of fractional precision stored in the
     * resulting Decimal. So \c Decimal("0.00") is stored with two digits of
     * fractional precision. However it is still the case that
     * <tt> Decimal("0.00") == Decimal("0") </tt>.
     * Note leading negative signs in front of \c Decimal("0") or its
     * equivalents are \e not stored.
     *
     * Exception safety: strong guarantee.
     */
    template <typename charT, typename traits, typename Alloc>
    explicit Decimal(std::basic_string<charT, traits, Alloc> const& str);

    /**
     * Precondition: the string must be null-terminated.
     *
     * Behaviour re. exceptions is the same as for the constructor
     * which takes a std::string.
     */
    explicit Decimal(char const* str);

    /**
     * Precondition: the string must be null-terminated.
     *
     * Behaviour re. exceptions is the same as for the constructor which
     * takes a std::wstring.
     */
    explicit Decimal(wchar_t const* str);

    Decimal(Decimal const&) = default;
    Decimal(Decimal&&) = default;
    Decimal& operator=(Decimal const&) = default;
    Decimal& operator=(Decimal&&) = default;
    ~Decimal() = default;

    /**
     * @exception DecimalAdditionException thrown if addition
     * would cause overflow. If this occurs, the left hand operand
     * will be unchanged from
     * its original value (and the right hand operand, as it is passed by
     * value, will also be unchanged).
     *
     * @exception DecimalRangeException thrown if fractional precision
     * cannot be maintained at the same level as that of the more precise
     * of the two numbers being
     * added. This ensures that - unlike in unchecked floating point
     * arithmetic - adding two non-zero Decimals is always yield a Decimal
     * that is equal to neither of the original Decimals (or else will throw
     * an exception). If this exception is thrown, the left hand operand will
     * be unchanged from its original value (as will the right hand operand,
     * since it is passed by value).
     *
     * Note trailing fractional zeroes are never "rationalized away" from the
     * result. Stored fractional precision is always maintained at the level
     * of the more precise of the operands, and if it cannot be, an exception
     * is thrown.
     *
     * Exception safety: strong guarantee.
     */
    Decimal& operator+=(Decimal);

    /**
     * @exception DecimalSubtractionException is thrown if
     * subtraction would cause overflow.
     *
     * @exception DecimalRangeException is thrown if fractional precision
     * cannot be maintained
     * at the same level as that of the more precise of the two numbers
     * involved (the minuend and the subrahend).
     * This ensures that - unlike in unchecked floating point
     * arithmetic - subtracting one non-zero number from another will always
     * yield a number that is equal to neither of the original numbers (or
     * else will throw an exception).
     *
     * Note trailing fractional zeroes are never "rationalized away" from the
     * result. Stored fractional precision is always maintained at the level
     * of the more precise of the operands, and if it cannot be, an exception
     * is thrown.
     *
     * Exception safety: strong guarantee.
     */
    Decimal& operator-=(Decimal);

    /**
     * @exception DecimalMultiplicationException thrown if multiplication
     * would cause overflow. If this occurs, the value of the left-hand
     * operand will be unchanged from its original value, as will the value
     * of the right-hand operand (since it is passed by value).
     *
     * Currently, for multiplication to be executed safely, it must be
     * the case that the underlying integral representations of the Decimals
     * being multiplied can themselves be multiplied without overflow. If
     * this cannot occur, then the Decimal multiplication operation will
     * throw an exception rather than proceeding with the operation. The
     * simplest way to avoid an exception from multiplication is to ensure
     * that the number of significant digits in the left multiplicand,
     * plus the number of significant digits in the right multiplicand,
     * is less than
     * the value returned by Decimal::maximum_precision(). Note
     * that all digits to the left of the decimal point (excluding the case
     * where the only
     * such digit is \c 0) are counted as significant digits.
     * In Decimals with fractional parts (digits to the right of the
     * decimal point), the significant
     * digits, going from left to right, start at the first non-zero digit,
     * and continue consecutively until the last non-zero digit is reached
     * (and the "boundary digits" just mentioned count as significant
     * digits). The negative sign and the decimal point
     * do not count as digits.
     *
     * Note also the smallest possible Decimal (the value returned by
     * Decimal::minimum()) cannot be multiplied, and
     * DecimalMultiplicationException is thrown if this is attempted.
     *
     * The fractional precision of the returned product is never more
     * than a number of decimal places to the right
     * of the decimal point equal to the value returned by
     * Decimal::maximum_precision(). The returned product is as precise as
     * possible within this constraint; however, trailing fractional zeroes
     * are always eliminated rather than being stored within the returned
     * product.
     *
     * Exception safety: strong guarantee.
     */
    Decimal& operator*=(Decimal);

    /**
     * @exception DecimalDivisionByZeroException is thrown if division by
     * zero is attempted.
     *
     * @exception DecimalDivisionException is thrown if division would cause
     * overflow.
     *
     * If an exception is thrown, the left-hand operand will be unchanged
     * from its original value, as will the right-hand operand (since it
     * is passed by value).
     *
     * The precision of the returned quotient is never more than
     * a number of decimal places to the right
     * of the decimal point, equal to the value
     * returned by Decimal::maximum_precision().
     * Also, the returned quotient never has
     * more significant (non-zero) digits than this. Division returns a
     * quotient that is as precise as possible within these constraints.
     * However, pointless trailing zeroes to the right of the
     * decimal point are eliminated rather than stored within the result.
     *
     * Currently, to be able to divide one Decimal by another,
     * it must be possible for the implementation of the division
     * function to increase the
     * fractional precision (number of places to the right of the decimal
     * point) of the dividend until it is greater than or equal to the
     * fractional precision of the divisor. In some cases it is not possible to
     * do this safely in which case an exception
     * is thrown. You can avoid this
     * possibility by ensuring that you only divide Decimals where the
     * fractional precision of the dividend is at least as great as that
     * of the divisor; or, failing that, where the sum of the number of
     * significant digits in the dividend, and the number of extra digits
     * of fractional precision that would need to be added to match the
     * fractional precision of the divisor, is less than the value returned
     * by Decimal::maximum_precision().
     *
     * In addition, an exception will be thrown in cases where the number
     * of significant digits in the dividend is equal to the return
     * value of Decimal::maximum_precision(). This is due to limitations
     * in the implementation. For division to succeed, the number of
     * significant digits in the dividend must be less than the value
     * returned by Decimal::maximum_precision(). Note
     * that all digits to the left of the decimal point (excluding the case
     * where the only
     * such digit is \c 0) are counted as significant digits.
     * In Decimals with fractional parts (digits to the right of the
     * decimal point), the significant
     * digits, going from left to right, start at the first non-zero digit,
     * and continue consecutively until the last non-zero digit is reached
     * (and the "boundary digits" just mentioned count as significant
     * digits). The negative sign and the decimal point
     * do not count as digits.
     *
     * Exception safety: strong guarantee.
     */
    Decimal& operator/=(Decimal);

    /**
     * @exception DecimalIncrementationException is thrown if incrementing
     * would cause overflow. If this happens, the Decimal will be unchanged
     * from its original value.
     *
     * Incrementing a Decimal never changes its fractional precision.
     *
     * Postfix and prefix version are both provided, with conventional
     * semantics.
     *
     * Exception safety: strong guarantee.
     */
    Decimal const& operator++();
    Decimal operator++(int);

    /** @exception DecimalDecrementationException is throw if decrementing
     * would cause overflow.
     *
     * Decrementing a Decimal never changes its fractional precision.
     *
     * Postfix and prefix version are both provided, with conventional
     * semantics.
     *
     * Exception safety: strong guarantee.
     */
    Decimal const& operator--();
    Decimal operator--(int);

    /**
     * Less-than operator. Compares Decimals by value.
     *
     * Exception safety: nothrow guarantee.
     */
    bool operator<(Decimal) const;

    /**
    * Equality operator. Compares Decimals by value.
    * Note the following evaluates to \c true: \n
    * Decimal("-0.000") == Decimal("0");
    *
    * Exception safety: nothrow guarantee.
    */
    bool operator==(Decimal) const;

    /**
     * Return the underlying integer representing the Decimal.
     *
     * Exception safety: nothrow guarantee.
     */
    int_type intval() const;

    /**
     * Return the number of digits of fractional precision in the
     * Decimal, i.e. the number of digits to the right of the decimal
     * point.
     *
     * Exception safety: nothrow guarantee.
     */
    places_type places() const;

    /**
     * Returns the largest possible Decimal number
     *
     * Exception safety: nothrow guarantee.
     */
    static Decimal maximum();

    /**
     * Returns the smallest possible Decimal number
     *
     * Exception safety: nothrow guarantee.
     */
    static Decimal minimum();

    /**
     * Returns the maximum number of digits of precision
     *
     * Exception safety: nothrow guarantee.
     */
    static places_type maximum_precision();

private:

    /**
     * Sets the number of decimal places of precision to
     * the right of the decimal point, while also rescaling the
     * underlying integer (which may involve rounding) to preserve
     * the same order of magnitude.
     *
     * For example:
     * @code
     * Decimal d0("90.23457");
     * d0.rescale(3);
     * assert(d0 == Decimal("90.235"));
     * d0.rescale(5);
     * assert(d0 == Decimal("90.23500"));
     * assert(d0 == Decimal("90.235"));
     * assert(d0.precision() == 3);
     * @endcode
     *
     * @param p_places the new number of decimal places (i.e. number
     * of digits of precision to the right of the decimal point)
     *
     * If p_places exceeds s_max_places, or if the function cannot otherwise
     * execute safely, an exception is \e not thrown, but
     * rather a non-zero value is returned to indicate error. If this occurs
     * the unsafe operation is not actually executed, but rather the Decimal
     * is retained in its original state.
     *
     * The function is non-throwing primarily for reasons of efficiency.
     *
     * @returns an integer indicating whether the operation was successful,
     * viz. 0 if successful, otherwise a non-zero value.
     */
    int rescale(places_type p_places);

    /**
     * Where the final digit(s) of the Decimal number are '0', this
     * method "chops off the zeroes" by reducing the number of
     * decimal places, while re-scaling the underlying integer to
     * preserve the same order of magnitude.
     *
     * For example: "0.3234000" rationalizes to "0.3234".
     *
     * If there are no trailing zeroes, then the function does nothing.
     *
     * A minimum number of places can be set, so that the number of digits
     * of fractional precision is not reduced below this number of places.
     *
     * For example, with a minimum number places of 5, "0.2324000"
     * rationalizes to "0.23240".
     *
     * @parameter min_places is the minimum number of decimal places to retain
     * to the right of the decimal point.
     */
    void rationalize(places_type min_places = 0);

    /**
     * Base of arithmetic. I can't imagine this ever being equal to anything
     * other than 10.
     */
    static int_type constexpr s_base = 10;

    /**
     * Threshold at which rounding goes up rather than down.
     */
    static int_type constexpr s_rounding_threshold = 5;

    /**
     * Maximum number of decimal places of precision to the right of
     * the decimal point.
     */
    static size_t const s_max_places;

    /**
     * Largest possible Decimal.
     */
    static Decimal const s_maximum;

    /**
     * Smallest possible Decimal.
     */
    static Decimal const s_minimum;

    /**
     * Number of digits of precision to the right of the decimal point.
     */
    places_type m_places;

    /**
     * Underlying integer representation of Decimal number.
     */
    int_type m_intval;

    /**
     * Convert two Decimal objects to the same number of places by converting
     * the one with the lesser number of places to the same number of places
     * as the one with the greater number of places (while rescaling to
     * maintain the same order of magnitude).
     *
     * @throws DecimalRangeException if the operation would cause
     * overflow.
     */
    static void co_normalize(Decimal&, Decimal&);

    /**
     * Power of 10 by which the underlying integer is implicitly divided.
     */
    int_type implicit_divisor() const;

    /** This constructor is deliberately unimplemented. Ensures if an int or
     * a convertible-to-int is passed to constructor, compilation will fail.
     */
    explicit Decimal(int);

    /**
     * Called by output operator. This is not designed to be called by
     * other functions. May throw boost::bad_lexical_cast (would be rare)
     * or std::bad_alloc (even if exceptions not enabled on oss).
     * Writes a Decimal number backwards on a stream. (Backwards is
     * easier.)
     */
    template <typename charT, typename traits>
    void output_aux(std::basic_ostream<charT, traits>& oss) const;

    // Auxiliary class to help with char and wchar_t literals.
    template <typename charT>
    struct CharacterProvider
    {
        static charT constexpr null = '\0';
        static charT constexpr plus = '+';
        static charT constexpr minus = '-';
    };

}; // class Decimal

// Helper function

namespace detail
{

template <typename charT>
static bool is_digit(charT c);

}  // namespace detail

// non-member functions - declarations

/** Write to an output stream.
 *
 * Exception safety: provides nothrow guarantee, \e unless exceptions
 * have been enabled for the output stream. In the
 * event of output failure, std::ios_base::badbit will be set on the
 * stream; but the setting of this flag will trigger an exception only if
 * the client has enabled exceptions for std::ios_base::badbit for this
 * stream. (At the time of writing this is not common practice.) The thrown
 * exception will be an instance of std::ios_base::failure. This might be
 * caused by internal memory allocation failure in the body of this function
 * (extremely unlikely); or it might be caused by an "external" error, e.g.
 * a disk being removed during the course of writing to the disk.
 *
 * Output is sensitive to the std::numpunct facet of the locale of the
 * stream being written to. "Thousands" separators, digit groupings and
 * the decimal point sign will adjust according to the facet. However,
 * jewel::Decimal does NOT currently support locales set by Boost.Locale.
 * This is a significant shortcoming, since Boost.Locale offers superior
 * localization facilities to those of the standard library.
 */
template <typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>&, Decimal const&);

/** Read from a std::istream
 *
 * @relates Decimal
 *
 * If the sequence of characters read from the stream is such that
 * it cannot be validly converted to a \c Decimal (see the \c Decimal
 * constructor that takes a \c std::string \c const& parameter, for
 * the circumstances in which this can occur), an exception is \c not
 * generally thrown, but rather the input stream will have
 * std::ios_base::failbit set on the stream, per the common convention.
 * In this case, the Decimal argument then retains
 * the value it had prior to commencement of the read operation. However,
 * an exception viz. std::ios_base::failure \e will be thrown if this
 * occurs where the input stream has had exceptions enabled for
 * std::ios_base::failbit. This is in
 * accordance with standard library convention. There is also an (extremely
 * small) chance of memory allocation failure during the read operation.
 * In this case, std::ios::badbit, and
 * an exception, being an instance of std::ios_base::failure, will be thrown
 * if and only if exceptions have been enabled for badbit for the stream.
 *
 * Exception safety: nothrow guarantee, unless exceptions have
 * been enabled for std::ios_base::failbit or std::ios_base::badbit for the
 * stream (see above).
 */
template <typename charT, typename traits>
std::basic_istream<charT, traits>&
operator>>(std::basic_istream<charT, traits>&, Decimal&);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator+=, and
 * throws under the same circumstances.
 */
Decimal const operator+(Decimal lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator-=, and
 * throws under the same circumstances.
 */
Decimal const operator-(Decimal lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator*=, and
 * throws under the same circumstances.
 */
Decimal const operator*(Decimal lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator/=, and
 * throws under the same circumstances.
 */
Decimal const operator/(Decimal lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator==.
 */
bool operator!=(Decimal const& lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator< and
 * of operator==.
 */
bool operator<=(Decimal const& lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator<.
 */
bool operator>(Decimal const& lhs, Decimal const& rhs);

/**
 * @relates Decimal
 *
 * Behaves as would be expected given the behaviour of operator> and
 * of operator==.
 */
bool operator>=(Decimal const& lhs, Decimal const& rhs);

/** Unary minus
 *
 * @relates Decimal
 *
 * @throws DecimalUnaryMinusException if you try to apply unary
 * minus to a value for which this is unsafe; for example, where the
 * underlying integral representation is \c long, it will be unsafe
 * to take the negative value of the Decimal corresponding to LONG_MIN
 * (which would then be the value returned by Decimal::minimum()).
 *
 * Exception safety: strong guarantee.
 */
Decimal operator-(Decimal const& d);

/** Unary plus
 *
 * Does what you would expect.
 *
 * @relates Decimal
 *
 * Exception safety: nothrow guarantee.
 */
Decimal operator+(Decimal const& d);

/** Rounding function
 *
 * @relates Decimal
 *
 * @param x The Decimal number to be rounded.
 * @param decimal_places The number of decimal digits after the
 * zero to which you wish to round. Should be a \e Decimal::places_type.
 *
 * Note if you round to a number of decimal places greater than the current
 * fractional precision, it will return a Decimal with the requested
 * fractional precision (filling in the extra places effectively with zeroes).
 * If this cannot be safely done an exception will be thrown.
 *
 * @returns A decimal number by value (distinct from x, which is not changed).
 * @exception DecimalRangeException thrown if achieving the requested
 * degree of precision would cause overflow.
 *
 * Exception safety: strong guarantee.
 */
Decimal round(Decimal const& x, Decimal::places_type decimal_places);

}  // namespace jewel

// ****************//

#include "assert.hpp"
#include "decimal_exceptions.hpp"
#include "exception.hpp"

namespace jewel
{

// SPECIALIZATIONS - must come first

namespace detail
{

template <>
bool is_digit<char>(char c)
{
    return std::isdigit(c);
}

template <>
bool is_digit<wchar_t>(wchar_t c)
{
    return std::iswdigit(c);
}

}  // namespace detail

// IMPLEMENTATIONS

template <typename charT, typename traits, typename Alloc>
Decimal::Decimal(std::basic_string<charT, traits, Alloc> const& str):
    m_places(0),
    m_intval(0)
{
    // NOTE In regards to the restriction enforced by this static_assert,
    // the ONLY reason this restriction is in place is that types other
    // than std::string and std::wstring are UNTESTED. It may well be
    // that the ONLY action required to make this work perfectly well with other
    // types is to get rid of the static_assert.
    static_assert
    (   std::is_same<decltype(str), std::string const&>::value ||
        std::is_same<decltype(str), std::wstring const&>::value,
        "Decimal constructor expected either std::string const& or "
        "std::wstring const&, but received some other type."
    );

    typedef typename std::basic_string<charT> stringT;
    typedef typename stringT::size_type sz_t;

    std::locale const loc;  // global locale
    charT const spot_char =
        std::use_facet<std::numpunct<charT> >(loc).decimal_point();
    charT const null_char = CharacterProvider<charT>::null;
    charT const plus_char = CharacterProvider<charT>::plus;
    charT const minus_char = CharacterProvider<charT>::minus;

    // Writing through iterators here to make it as fast as I reasonably
    // can.
    //
    // This seems to be about as fast as using indexing, but roughly 25%
    // faster than using push_back.
    //
    // I've got plentiful asserts to ensure I don't read or write off the
    // end.
    //
    // Note the lexical cast near the end accounts for a huge chunk of the
    // execution time.
    //
    // Of course, if I want extremely fast construction of a Decimal,
    // the constructor-from-string is not the best constructor to achieve
    // that.

    if (str.empty())
    {
        JEWEL_THROW
        (   DecimalFromStringException,
            "Cannot construct Decimal from an empty string"
        );
    }
    sz_t const str_size = str.size();

    // To hold string representation of underlying integer...
    // We will decrease this size later if there's a spot (decimal point)
    // as we won't hold the spot in str_rep.
    stringT str_rep(str_size, null_char);
    typename stringT::const_iterator si = str.begin();  // Read through this
    typename stringT::iterator ri = str_rep.begin();    // Write through this

    if (*si == minus_char || *si == plus_char)
    {
        JEWEL_ASSERT (ri < str_rep.end());
        *ri++ = *si++;
    }

    typename stringT::const_iterator const str_end = str.end();
    for ( ; *si != spot_char && si != str_end; ++si, ++ri)
    {
        JEWEL_ASSERT (si < str_end);
        if (!detail::is_digit(*si))
        {
            JEWEL_THROW
            (   DecimalFromStringException,
                "Invalid string passed to Decimal constructor."
            );
        }
        JEWEL_ASSERT (ri < str_rep.end());
        *ri = *si;
    }
    sz_t spot_position = 0;   // for the position of decimal point
    if (*si == spot_char)
    {
        // We have a spot.
        // We have a str_rep that's one too big
        sz_t reduced_size = str_size;
        JEWEL_ASSERT (reduced_size > 0);
        str_rep.resize(--reduced_size);
        JEWEL_ASSERT (reduced_size == str_rep.size());
        JEWEL_ASSERT (reduced_size < str_size);
        JEWEL_ASSERT (str_size >= 1);

        // Jump over the spot in str
        ++si;

        // Now let's get the remaining the digits
        JEWEL_ASSERT (str_end == str.end());
        for ( ; si != str_end; ++si, ++ri)
        {
            ++spot_position;        // To count no. of fractional places
            JEWEL_ASSERT (si < str_end);
            if (!detail::is_digit(*si))
            {
                JEWEL_ASSERT (m_places == 0);
                JEWEL_ASSERT (m_intval == 0);
                JEWEL_THROW
                (   DecimalFromStringException,
                    "Invalid string passed to Decimal constructor."
                );
            }
            JEWEL_ASSERT (reduced_size == str_rep.size());
            JEWEL_ASSERT (ri < str_rep.end());
            *ri = *si;
        }
    }
    if (spot_position > s_max_places)
    {
        JEWEL_THROW
        (   DecimalRangeException,
            "Attempt to set m_places to a value exceeding that returned by "
            "Decimal::maximum_precision()."
        );
    }
    if (str_rep.size() <= 1)
    {
        if
        (   str_rep.empty() ||
            str_rep == stringT(1, minus_char) ||
            str_rep == stringT(1, plus_char)
        )
        {
            JEWEL_THROW
            (   DecimalFromStringException,
                "Attempt to create a Decimal without any digits."
            );
        }
    }
    try
    {
        // This lexical cast accounted for over half of the execution
        // time in this function last time I checked.
        m_intval = boost::lexical_cast<int_type>(str_rep);
    }
    catch (boost::bad_lexical_cast&)
    {
        JEWEL_THROW
        (   DecimalRangeException,
            "Attempt to create Decimal that is either too large, too small "
            "or too precise than is supported by the Decimal implementation."
        );
    }
    m_places = boost::numeric_cast<places_type>(spot_position);
}

inline
Decimal::Decimal(char const* str)
{
    *this = Decimal(std::string(str));
}

inline
Decimal::Decimal(wchar_t const* str)
{
    *this = Decimal(std::wstring(str));
}

inline
Decimal::int_type
Decimal::intval() const
{
    return m_intval;
}

inline
Decimal::places_type
Decimal::places() const
{
    return m_places;
}

// Inline static class functions

inline
Decimal::places_type Decimal::maximum_precision()
{
    return s_max_places;
}

inline
Decimal
Decimal::minimum()
{
    return s_minimum;
}

inline
Decimal
Decimal::maximum()
{
    return s_maximum;
}

// Inline non-member functions

inline
Decimal const
operator+(Decimal lhs, Decimal const& rhs)
{
    lhs += rhs;
    return lhs;
}

inline
Decimal const
operator-(Decimal lhs, Decimal const& rhs)
{
    lhs -= rhs;
    return lhs;
}

inline
Decimal const
operator*(Decimal lhs, Decimal const& rhs)
{
    lhs *= rhs;
    return lhs;
}

inline
Decimal const
operator/(Decimal lhs, Decimal const& rhs)
{
    lhs /= rhs;
    return lhs;
}

inline
Decimal
operator+(Decimal const& d)
{
    return d;
}

inline
bool
operator!=(Decimal const& lhs, Decimal const& rhs)
{
    return !(lhs == rhs);
}

inline
bool
operator>(Decimal const& lhs, Decimal const& rhs)
{
    return rhs < lhs;
}

inline
bool
operator<=(Decimal const& lhs, Decimal const& rhs)
{
    return (lhs == rhs) || (lhs < rhs);
}

inline
bool
operator>=(Decimal const& lhs, Decimal const& rhs)
{
    return (lhs == rhs) || (rhs < lhs);
}

// Output

template <typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, Decimal const& d)
{
    if (!os)
    {
        return os;
    }
    try
    {
        // We will write to a basic_ostringstream initially. Only at the last
        // minute will we write to os itself.
        std::basic_ostringstream<charT, traits> ss;

        // Whatever exception-throwing behaviour the client has set for os
        // should also be mirrored in ss.
        ss.exceptions(os.exceptions());

        ss.imbue(os.getloc());
        d.output_aux(ss);
        if (!ss)
        {
            // If any error flags have been set in ss, we now
            // mirror them here in os, and return rather
            // than potentially corrupt data to os.
            os.setstate(ss.rdstate());
            return os;
        }
        JEWEL_ASSERT (ss);
        std::basic_string<charT> const s = ss.str();
        std::reverse_copy
        (   s.begin(),
            s.end(),
            std::ostream_iterator<charT, charT, traits>(os)
        );
    }
    catch (std::exception&)
    {
        // Exception could be std::bad_alloc from failed allocation of
        // ostringstream or string (though both are
        // extremely unlikely).
        // Possibly others? Catch std::exception to be sure.
        os.setstate(std::ios_base::badbit);
    }
    return os;
}

template <typename charT, typename traits>
void
Decimal::output_aux(std::basic_ostream<charT, traits>& oss) const
{
    using std::locale;
    using std::numpunct;
    using std::reverse_copy;
    using std::use_facet;
    typedef typename std::basic_string<charT> stringT;
    typedef typename stringT::size_type str_sz;
    typedef typename std::basic_ostringstream<charT> ostringstreamT;
    typedef typename std::ostream_iterator<charT, charT, traits> ostream_itT;

    // Record target locale
    locale const loc(oss.getloc());
    charT const decimal_point =
        use_facet<numpunct<charT> >(loc).decimal_point();

    // We will be "manually" reflecting the locale's numpunct facet
    // in what we write to oss. If there is already a non-C
    // locale on oss, we get rid of it now. We don't want
    // some other locale's numpunct facet interfering with
    // our manual labours.
    oss.imbue(locale::classic());

    // Now we write the number BACKWARDS onto oss. It's easier
    // this way, especially when it comes to processing
    // "thousands separators".

    // special case of zero
    if (m_intval == 0)
    {
        if (m_places > 0)
        {
            oss << stringT(m_places, oss.widen('0')) << decimal_point;
        }
        oss << oss.widen('0');
    }

    // special case of smallest possible m_intval - as we
    // cannot take the absolute value below
    else if (m_intval == std::numeric_limits<Decimal::int_type>::min())
    {
        JEWEL_ASSERT (m_places == 0);
        ostringstreamT tempstream;
        tempstream.imbue(loc);
        tempstream << m_intval;
        stringT const tempstring = tempstream.str();
        reverse_copy
        (   tempstring.begin(),
            tempstring.end(),
            ostream_itT(oss)
        );
    }

    else
    {
        // Our starting point is the stringT of digits representing
        // the absolute value of the underlying integer.
        ostringstreamT tempstream;
        tempstream.imbue(locale::classic());
        tempstream << std::abs(m_intval);
        stringT s = tempstream.str();

        // Write the fractional part
        typename stringT::const_reverse_iterator const rend = s.rend();
        typename stringT::const_reverse_iterator rit = s.rbegin();
        str_sz digits_written  = 0;
        for
        (   ;
            (digits_written != m_places) && (rit != rend);
            ++rit, ++digits_written
        )
        {
            oss << *rit;
        }

        // Deal with any "filler zeroes" required in the
        // fractional part
        while (digits_written != m_places)
        {
            oss << oss.widen('0');
            ++digits_written;
        }

        // Write the decimal point if required
        if (m_places != 0) oss << decimal_point;

        // Write the whole part

        // Get format specifier for digit grouping
        std::string const grouping =
            use_facet< numpunct<charT> >(loc).grouping();
        if (grouping.empty())
        {
            // We don't have to deal with digit grouping
            for
            (   ;
                rit != rend;
                ++rit, ++digits_written
            )
            {
                oss << *rit;
            }
        }
        else
        {
            // We have to deal with digit grouping
            charT const separator =
                use_facet<numpunct<charT> >(loc).thousands_sep();
            std::string::const_iterator grouping_it = grouping.begin();
            JEWEL_ASSERT (!grouping.empty());
            std::string::const_iterator const last_group_datum
                = grouping.end() - 1;
            str_sz digits_written_this_group = 0;
            for
            (   ;
                rit != rend;
                ++rit, ++digits_written, ++digits_written_this_group
            )
            {
                if
                (   digits_written_this_group ==
                    static_cast<str_sz>(*grouping_it)
                )
                {
                    oss << separator;
                    digits_written_this_group = 0;
                    if (grouping_it != last_group_datum) ++grouping_it;
                }
                oss << *rit;
            }
        }

        // Write a leading zero if required
        if (digits_written == m_places)
        {
            oss << oss.widen('0');
        }

        // Write negative sign if required
        if (m_intval < 0) oss << '-';
    }
    #ifdef JEWEL_PERFORM_DECIMAL_OUTPUT_FAILURE_TEST
        // We cause bad memory allocation here to provoke
        // failure. This is to test how Decimal output
        // operator<< (which calls this function) handles
        // failure.
        std::string grow_me("a");
        while (true)
        {
            grow_me += grow_me;
        }
    #endif
    return;
}

// Input

template <typename charT, typename traits>
std::basic_istream<charT, traits>&
operator>>(std::basic_istream<charT, traits>& is, Decimal& d)
{
    if (!is)
    {
        return is;
    }
    Decimal temp = d;
    try
    {
        std::string str;
        is >> str;
        if (!is)
        {
            return is;
        }
        try
        {
            temp = Decimal(str);
        }
        catch (DecimalException&)
        {
            is.setstate(std::ios_base::failbit);
            return is;
        }
        d = temp;
    }
    catch (std::bad_alloc&)
    {
        is.setstate(std::ios_base::badbit);
        return is;
    }
    return is;
}

} // namespace jewel

#endif  // GUARD_decimal_hpp_0809249049429432


#ifndef TYPES_H
#define TYPES_H

#include <Eigen/Core>
#include <functional>
#include <unordered_map>
#include <utility>

namespace Optima {

/// Pair of vectors defining the bounds of the search space
typedef std::pair<Eigen::ArrayXd, Eigen::ArrayXd> Bounds;
/// Typedef for a parameter space
typedef std::unordered_map<std::string, std::pair<double, double>>
    ParameterSpace;
/// Typedef for a paramerter set
typedef std::unordered_map<std::string, double> Parameters;
/// Typedef for a cost function
typedef std::function<double(Parameters const &)> CostFunction;

}

#endif // TYPES_H


// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.

// This file was modified by Oracle on 2013, 2014, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.

// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Use, modification and distribution is subject to 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_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP

#include <algorithm>
#include <vector>

#include <boost/range/empty.hpp>

#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/algorithms/detail/relate/result.hpp>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {

template <typename Point1, typename Point2>
struct point_point
{
    static const bool interruption_enabled = false;

    template <typename Result, typename Strategy>
    static inline void apply(Point1 const& point1, Point2 const& point2,
                             Result & result,
                             Strategy const& /*strategy*/)
    {
        bool equal = detail::equals::equals_point_point(point1, point2);
        if ( equal )
        {
            relate::set<interior, interior, '0'>(result);
        }
        else
        {
            relate::set<interior, exterior, '0'>(result);
            relate::set<exterior, interior, '0'>(result);
        }

        relate::set<exterior, exterior, result_dimension<Point1>::value>(result);
    }
};

template <typename Point, typename MultiPoint>
std::pair<bool, bool> point_multipoint_check(Point const& point, MultiPoint const& multi_point)
{
    bool found_inside = false;
    bool found_outside = false;

    // point_in_geometry could be used here but why iterate over MultiPoint twice?
    // we must search for a point in the exterior because all points in MultiPoint can be equal

    typedef typename boost::range_iterator<MultiPoint const>::type iterator;
    iterator it = boost::begin(multi_point);
    iterator last = boost::end(multi_point);
    for ( ; it != last ; ++it )
    {
        bool ii = detail::equals::equals_point_point(point, *it);

        if ( ii )
            found_inside = true;
        else
            found_outside = true;

        if ( found_inside && found_outside )
            break;
    }

    return std::make_pair(found_inside, found_outside);
}

template <typename Point, typename MultiPoint, bool Transpose = false>
struct point_multipoint
{
    static const bool interruption_enabled = false;

    template <typename Result, typename Strategy>
    static inline void apply(Point const& point, MultiPoint const& multi_point,
                             Result & result,
                             Strategy const& /*strategy*/)
    {
        if ( boost::empty(multi_point) )
        {
            // TODO: throw on empty input?
            relate::set<interior, exterior, '0', Transpose>(result);
            return;
        }

        std::pair<bool, bool> rel = point_multipoint_check(point, multi_point);

        if ( rel.first ) // some point of MP is equal to P
        {
            relate::set<interior, interior, '0', Transpose>(result);

            if ( rel.second ) // a point of MP was found outside P
            {
                relate::set<exterior, interior, '0', Transpose>(result);
            }
        }
        else
        {
            relate::set<interior, exterior, '0', Transpose>(result);
            relate::set<exterior, interior, '0', Transpose>(result);
        }

        relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
    }
};

template <typename MultiPoint, typename Point>
struct multipoint_point
{
    static const bool interruption_enabled = false;

    template <typename Result, typename Strategy>
    static inline void apply(MultiPoint const& multi_point, Point const& point,
                             Result & result,
                             Strategy const& strategy)
    {
        point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result, strategy);
    }
};

template <typename MultiPoint1, typename MultiPoint2>
struct multipoint_multipoint
{
    static const bool interruption_enabled = true;

    template <typename Result, typename Strategy>
    static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2,
                             Result & result,
                             Strategy const& /*strategy*/)
    {
        {
            // TODO: throw on empty input?
            bool empty1 = boost::empty(multi_point1);
            bool empty2 = boost::empty(multi_point2);
            if ( empty1 && empty2 )
            {
                return;
            }
            else if ( empty1 )
            {
                relate::set<exterior, interior, '0'>(result);
                return;
            }
            else if ( empty2 )
            {
                relate::set<interior, exterior, '0'>(result);
                return;
            }
        }

// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED

// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
//       so if e.g. only I/I must be analysed we musn't check the other MPt

// TODO: Also, the geometry with the smaller number of points may be analysed first
        //if ( boost::size(multi_point1) < boost::size(multi_point2) )

        // NlogN + MlogN
        bool all_handled = search<false>(multi_point1, multi_point2, result);

        if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )
            return;

        // MlogM + NlogM
        search<true>(multi_point2, multi_point1, result);
    }

    template <bool Transpose,
              typename SortedMultiPoint,
              typename IteratedMultiPoint,
              typename Result>
    static inline bool search(SortedMultiPoint const& sorted_mpt,
                              IteratedMultiPoint const& iterated_mpt,
                              Result & result)
    {
        // sort points from the 1 MPt
        typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
        std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
        std::sort(points.begin(), points.end(), less());

        bool found_inside = false;
        bool found_outside = false;

        // for each point in the second MPt
        typedef typename boost::range_iterator<IteratedMultiPoint const>::type iterator;
        for ( iterator it = boost::begin(iterated_mpt) ;
              it != boost::end(iterated_mpt) ; ++it )
        {
            bool ii =
                std::binary_search(points.begin(), points.end(), *it, less());
            if ( ii )
                found_inside = true;
            else
                found_outside = true;

            if ( found_inside && found_outside )
                break;
        }

        // an optimization
        bool all_handled = false;

        if ( found_inside ) // some point of MP2 is equal to some of MP1
        {
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
//       so if e.g. only I/I must be analysed we musn't check the other MPt

            relate::set<interior, interior, '0', Transpose>(result);

            if ( found_outside ) // some point of MP2 was found outside of MP1
            {
                relate::set<exterior, interior, '0', Transpose>(result);
            }
        }
        else
        {
            relate::set<interior, exterior, '0', Transpose>(result);
            relate::set<exterior, interior, '0', Transpose>(result);

            // if no point is intersecting the other MPt then we musn't analyse the reversed case
            all_handled = true;
        }

        relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);

        return all_handled;
    }
};

}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP


// Copyright (C) 2003  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.

#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>

#include <dlib/conditioning_class.h>

#include "tester.h"
#include "conditioning_class.h"

namespace
{

    class conditioning_class_tester : public tester
    {
    public:
        conditioning_class_tester (
        ) :
            tester ("test_conditioning_class_c",
                    "Runs tests on the conditioning_class checked components.")
        {}

        void perform_test (
        )
        {
            dlog << LINFO << "testing kernel_1a_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_1a_c,
                conditioning_class<2>::kernel_1a_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_2a_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_2a_c,
                conditioning_class<2>::kernel_2a_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_3a_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_3a_c,
                conditioning_class<2>::kernel_3a_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_4a_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_4a_c,
                conditioning_class<2>::kernel_4a_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_4b_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_4b_c,
                conditioning_class<2>::kernel_4b_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_4c_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_4c_c,
                conditioning_class<2>::kernel_4c_c
                >();
            print_spinner();

            dlog << LINFO << "testing kernel_4d_c";
            conditioning_class_kernel_test<
                conditioning_class<256>::kernel_4d_c,
                conditioning_class<2>::kernel_4d_c
                >();
            print_spinner();

        }
    } a;

}


//
//  Copyright (c) 2000-2002
//  Joerg Walter, Mathias Koch
//
//  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)
//
//  The authors gratefully acknowledge the support of
//  GeNeSys mbH & Co. KG in producing this work.
//

#include <boost/numeric/interval.hpp>
#include <boost/numeric/interval/io.hpp>
#include "../bench1/bench11.cpp"

#ifdef USE_FLOAT
template struct bench_1<boost::numeric::interval<float>, 3>;
template struct bench_1<boost::numeric::interval<float>, 10>;
template struct bench_1<boost::numeric::interval<float>, 30>;
template struct bench_1<boost::numeric::interval<float>, 100>;
#endif

#ifdef USE_DOUBLE
template struct bench_1<boost::numeric::interval<double>, 3>;
template struct bench_1<boost::numeric::interval<double>, 10>;
template struct bench_1<boost::numeric::interval<double>, 30>;
template struct bench_1<boost::numeric::interval<double>, 100>;
#endif

#ifdef USE_BOOST_COMPLEX
#ifdef USE_FLOAT
template struct bench_1<boost::complex<boost::numeric::interval<float> >, 3>;
template struct bench_1<boost::complex<boost::numeric::interval<float> >, 10>;
template struct bench_1<boost::complex<boost::numeric::interval<float> >, 30>;
template struct bench_1<boost::complex<boost::numeric::interval<float> >, 100>;
#endif

#ifdef USE_DOUBLE
template struct bench_1<boost::complex<boost::numeric::interval<double> >, 3>;
template struct bench_1<boost::complex<boost::numeric::interval<double> >, 10>;
template struct bench_1<boost::complex<boost::numeric::interval<double> >, 30>;
template struct bench_1<boost::complex<boost::numeric::interval<double> >, 100>;
#endif
#endif


#include <boost/test/included/unit_test.hpp>

#include <random>
#include <numeric>
#include <cstring>

#include <cereal/cereal.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/archives/xml.hpp>
#include <fstream>
#include <sstream>

#include "rfr/data_containers/default_data_container.hpp"
#include "rfr/splits/binary_split_one_feature_rss_loss.hpp"
#include "rfr/nodes/temporary_node.hpp"
#include "rfr/nodes/k_ary_node.hpp"
#include "rfr/trees/tree_options.hpp"
#include "rfr/trees/k_ary_tree.hpp"

#include "rfr/trees/binary_fanova_tree.hpp"

typedef double num_t;
typedef double response_t;
typedef unsigned int index_t;
typedef std::default_random_engine rng_t;

typedef rfr::data_containers::default_container<num_t, response_t, index_t> 			data_container_t;
typedef rfr::splits::binary_split_one_feature_rss_loss<num_t, response_t, index_t, rng_t> 	split_t;
typedef rfr::nodes::k_ary_node_full<2, split_t, num_t, response_t, index_t, rng_t> 		node_t;
typedef rfr::nodes::temporary_node<num_t, index_t> 											tmp_node_t;
typedef rfr::trees::k_ary_random_tree<2, node_t, num_t, response_t, index_t, rng_t>		tree_t;
typedef rfr::trees::binary_fANOVA_tree<split_t, num_t, response_t, index_t, rng_t>		fANOVA_tree_t;

data_container_t load_toy_data(){
	data_container_t data(2);

    std::string feature_file, response_file;

    feature_file  = std::string(boost::unit_test::framework::master_test_suite().argv[1]) + "toy_data_set_features.csv";
    response_file = std::string(boost::unit_test::framework::master_test_suite().argv[1]) + "toy_data_set_responses.csv";

    data.import_csv_files(feature_file, response_file);

	data.set_type_of_feature(1,10);

    BOOST_REQUIRE_EQUAL(data.num_data_points(), 100);

    return(data);
}

data_container_t load_diabetes_data(){
	data_container_t data(10);

    std::string feature_file, response_file;

    feature_file  = std::string(boost::unit_test::framework::master_test_suite().argv[1]) + "diabetes_features.csv";
    response_file = std::string(boost::unit_test::framework::master_test_suite().argv[1]) + "diabetes_responses.csv";

    data.import_csv_files(feature_file, response_file);
    return(data);
}

// Test does not actually check the correctness of the split or anything.
// It makes sure everything compiles and runs

BOOST_AUTO_TEST_CASE( binary_tree_test ){

	auto data = load_toy_data();

    data.set_type_of_feature(1, 4);

    rfr::trees::tree_options<num_t, response_t, index_t> tree_opts;

    tree_opts.max_features = 1;
    tree_opts.max_depth = 3;

    rng_t rng_engine;

    for (auto i = 0; i <1; i++){
	tree_t the_tree;
	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	char filename[100];
		sprintf(filename, "/tmp/tree_%i.tex", i);
		the_tree.save_latex_representation(filename);
    }

	tree_t the_tree1;
	the_tree1.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	the_tree1.save_latex_representation("/tmp/rfr_test_tree1.tex");

	BOOST_REQUIRE(the_tree1.check_split_fractions(1e-6));

	std::ostringstream oss;

	{
		cereal::XMLOutputArchive oarchive(oss);
		oarchive(the_tree1);
	}

	tree_t the_tree2;
	{
		std::istringstream iss(oss.str());
		cereal::XMLInputArchive iarchive(iss);
		iarchive(the_tree2);
	}

    the_tree2.save_latex_representation("/tmp/rfr_test_tree2.tex");

	for (auto i=0u; i < data.num_data_points(); ++i){
		auto v1 = the_tree1.predict(data.retrieve_data_point(i));
		auto v2 = the_tree2.predict(data.retrieve_data_point(i));
		BOOST_REQUIRE_EQUAL(v1,v2);
	}

}

// Test does not actually check the correctness of the split or anything.
// It makes sure everything compiles and runs
// TODO: add tests for the partitions and marginalized predictions
BOOST_AUTO_TEST_CASE( binary_fANOVA_tree_test ){

	auto data = load_toy_data();

    data.set_type_of_feature(1, 4);

    rfr::trees::tree_options<num_t, response_t, index_t> tree_opts;

    tree_opts.max_features = 2;
    tree_opts.max_depth = 10;

    rng_t rng_engine;

	fANOVA_tree_t the_tree;
	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	the_tree.predict(data.retrieve_data_point(1));

}

BOOST_AUTO_TEST_CASE( binary_tree_constraints_test ){

	auto data = load_diabetes_data();
    rfr::trees::tree_options<num_t, response_t, index_t> tree_opts;

    tree_opts.max_features = 2;
    tree_opts.max_depth = 3;

    rng_t rng_engine;

	tree_t the_tree;
	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);
	the_tree.save_latex_representation("/tmp/rfr.tex");
	BOOST_REQUIRE_EQUAL(the_tree.depth(), 3);

	tree_opts.max_depth = 1024;
	tree_opts.max_num_nodes = 15;
	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	BOOST_REQUIRE_EQUAL(the_tree.depth(), 3);
	BOOST_REQUIRE_EQUAL(the_tree.number_of_nodes(), 15);
	BOOST_REQUIRE_EQUAL(the_tree.number_of_leafs(), 8);

	tree_opts.max_depth = 1024;
	tree_opts.max_num_leaves = 16;
	tree_opts.max_num_nodes = 1024;
	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	BOOST_REQUIRE(the_tree.number_of_leafs() <= 16);
	BOOST_REQUIRE(the_tree.number_of_nodes() <= 31);

	tree_opts.max_num_leaves = 1024;
	tree_opts.max_num_nodes = 2048;
	tree_opts.min_weight_in_leaf = data.num_data_points()+1;

	the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng_engine);

	BOOST_REQUIRE_EQUAL(1, the_tree.number_of_nodes());

}

BOOST_AUTO_TEST_CASE(  second_binary_tree_constraints_test ){
	std::vector<num_t> y = {0,0,0, 0.001, 1, 1};

	std::vector<std::vector<num_t> > X =
    {{0},
     {1},
     {2},
     {3},
     {4},
     {5}};

	rng_t rng(12345);
	tree_t the_tree;
    rfr::trees::tree_options<num_t, response_t, index_t> tree_opts;

	tree_opts.max_features = 1;
	tree_opts.max_depth = 1;
	tree_opts.epsilon_purity = 1e-8;

	for (int iter=0; iter<2; iter++){

		data_container_t data(1);

		if (iter==1) data.set_type_of_feature(0,6);

		for (auto i=0u; i<y.size(); ++i)
			data.add_data_point(X[i], y[i]);

		tree_opts.min_weight_to_split = 1;
		tree_opts.min_samples_to_split = 1;
		tree_opts.min_weight_in_leaf = 1;
		tree_opts.min_samples_in_leaf = 1;

		the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng);

		auto stat1 = the_tree.leaf_statistic(data.retrieve_data_point(0));
		auto stat2 = the_tree.leaf_statistic(data.retrieve_data_point(5));

		BOOST_REQUIRE_EQUAL(3, the_tree.number_of_nodes());
		BOOST_REQUIRE_EQUAL(4, stat1.sum_of_weights());
		BOOST_REQUIRE_EQUAL(2, stat2.sum_of_weights());

		tree_opts.min_weight_to_split = 6;
		tree_opts.min_samples_to_split = 1;
		tree_opts.min_weight_in_leaf = 3;
		tree_opts.min_samples_in_leaf = 1;

		the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng);
		stat1 = the_tree.leaf_statistic(data.retrieve_data_point(0));
		stat2 = the_tree.leaf_statistic(data.retrieve_data_point(5));

		BOOST_REQUIRE_EQUAL(3, the_tree.number_of_nodes());
		BOOST_REQUIRE_EQUAL(3, stat1.sum_of_weights());
		BOOST_REQUIRE_EQUAL(3, stat2.sum_of_weights());

		// now the same with the number of samples in leaf

		tree_opts.min_weight_to_split = 1;
		tree_opts.min_samples_to_split = 6;
		tree_opts.min_weight_in_leaf = 1;
		tree_opts.min_samples_in_leaf = 3;

		the_tree.fit(data, tree_opts, std::vector<num_t>(data.num_data_points(), 1), rng);

		stat1 = the_tree.leaf_statistic(data.retrieve_data_point(0));
		stat2 = the_tree.leaf_statistic(data.retrieve_data_point(5));

		BOOST_REQUIRE_EQUAL(3, the_tree.number_of_nodes());
		BOOST_REQUIRE_EQUAL(3, stat1.sum_of_weights());
		BOOST_REQUIRE_EQUAL(3, stat2.sum_of_weights());

	}
}


#pragma once

/*
struct Coord {
  double x;
  double y;
  Coord(){}
  Coord(int x, int y) : x(x), y(y) {}
};
*/
#include <cmath>
#include <functional>
#include <vector>

#include <boost/geometry/geometries/geometries.hpp>
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> point;

class Coord {
   private:
   public:
	double x;
	double y;

	Coord() {}
	Coord(double x, double y) {
		this->x = x;
		this->y = y;
	}

	// double x() { return this->c[0]; }

	// double y() { return this->c[1]; }

	void change(double x, double y) {
		this->x = x;
		this->y = y;
	}

	point getBoostPoint() { return point(this->x, this->y); }

	// bool operator==(const Coord& other) { return this->x == other.x && this->y == other.y; }
};

inline bool operator==(const Coord& lhs, const Coord& rhs) { return std::abs(lhs.x - rhs.x) + std::abs(lhs.y - rhs.y) < 0.001; }
inline bool operator!=(const Coord& lhs, const Coord& rhs) { return std::abs(lhs.x - rhs.x) + std::abs(lhs.y - rhs.y) > 0.001; }

namespace std {

template <>
struct hash<Coord> {
	std::size_t operator()(const Coord& c) const {
		// Compute individual hash values for first,
		// second and third and combine them using XOR
		// and bit shifting:

		return (std::hash<double>()(c.x) ^ (std::hash<double>()(c.y) << 1));
	}
};
}


#pragma once

#include "Game/Components/InputComponent.hpp"

#include <Eigen/Dense>

class SnakeInputComponent : public InputComponent {
public:
    SnakeInputComponent(GameObject* gameObject);
    inline Eigen::Vector2f getInputVector() const {
        return inputVector;
    }
private:
    void onMove(const SDL_Event& event);

    const std::string ACTION_MOVE = "Move";
    Eigen::Vector2f inputVector { 1, 0 };
};


// Software License for MTL
//
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
//
// This file is part of the Matrix Template Library
//
// See also license.mtl.txt in the distribution.

#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>
#include <boost/numeric/mtl/utility/view_code.hpp>

using namespace std;
typedef std::complex<double> ct;

// This template should never be instantiated
template <int Code, typename Matrix>
struct check_type_aux
{
    static void apply() { MTL_STATIC_ASSERT((Code == 999), "View not folded correctly."); }
};

template <typename Value, typename Parameters>
struct check_type_aux<0, mtl::mat::dense2D<Value, Parameters> >
{    static void apply() {}  };

template <typename Matrix>
struct check_type_aux<2, mtl::mat::conj_view<Matrix> >
{    static void apply() {}  };

template <typename Matrix>
struct check_type_aux<4, mtl::mat::transposed_view<Matrix> >
{    static void apply() {}  };

template <typename Matrix>
struct check_type_aux<6, mtl::mat::hermitian_view<Matrix> >
{    static void apply() {}  };

template <int Code, typename Matrix>
void check_code()
{
    // cout << "View code is " << mtl::traits::view_code<Matrix>::value << '\n';
    // MTL_THROW_IF((Code != (mtl::traits::view_code<Matrix>::value & 6)), mtl::unexpected_result("Not correct view_code."));
    MTL_STATIC_ASSERT((Code == (mtl::traits::view_code<Matrix>::value & 6)), "Not correct view_code.");
}

template <int Code, typename Matrix>
void check_type(const Matrix&)
{
    check_code<Code, Matrix>();
    check_type_aux<Code, Matrix>::apply();
}

template <typename Matrix>
void check(const Matrix& A, int code)
{
    switch (code) {
      case 0: MTL_THROW_IF(A[1][0] != ct(3, 4), mtl::unexpected_result("In original matrix.")); break;
      case 2: MTL_THROW_IF(A[1][0] != ct(3, -4), mtl::unexpected_result("In conjugated matrix.")); break;
      case 4: MTL_THROW_IF(A[1][0] != ct(0, 1), mtl::unexpected_result("In transposed matrix.")); break;
      case 6: MTL_THROW_IF(A[1][0] != ct(0, -1), mtl::unexpected_result("In hermitian matrix.")); break;
    }
}

template <int Code, typename Matrix>
void inner_test(const Matrix& A, const char* text)
{
    cout << "\nChecking " << text << ", A is\n" << A;
    check(A, Code);
    check_type<Code>(A);

    cout << "conj(A) is\n" << mtl::conj(A);
    check(mtl::conj(A), Code ^ 2);
    check_type<Code ^ 2>(mtl::conj(A));

    cout << "trans(A) is\n" << trans(A);
    check(trans(A), Code ^ 4);
    check_type<Code ^ 4>(trans(A));

    cout << "hermitian(A) is\n" << hermitian(A);
    check(hermitian(A), Code ^ 6);
    check_type<Code ^ 6>(hermitian(A));
}

template <typename Matrix>
void test(Matrix& A)
{
    A= ct(2, 1), ct(0, 1),
       ct(3, 4), ct(5, 6);

    inner_test<0>(A, "original matrix");
    inner_test<2>(mtl::conj(A), "conjugated matrix");
    inner_test<4>(trans(A), "transposed matrix");
    inner_test<6>(hermitian(A), "Hermitian matrix");
}

int main(int, char**)
{
    using namespace mtl;

    dense2D<ct>    A(2, 2);

    test(A);

    return 0;
}


//==================================================================================================
/*!

  Copyright 2015 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#include <boost/simd/constant/minlog10.hpp>
#include <boost/simd/as.hpp>
#include <simd_test.hpp>

STF_CASE_TPL( "Check minlog10 behavior for integral types"
            , (std::uint32_t)(std::uint64_t)
              (std::int32_t)(std::int64_t)
            )
{
  using boost::simd::as;
  using boost::simd::detail::minlog10;
  using boost::simd::Minlog10;
  T ref = T(0);
  STF_TYPE_IS(decltype(Minlog10<T>()), T);
  STF_EQUAL(Minlog10<T>(), ref);
  STF_EQUAL(minlog10( as(T{}) ),ref);
}

STF_CASE_TPL( "Check minlog10 behavior for double"
            , (double)
            )
{
  using boost::simd::as;
  using boost::simd::detail::minlog10;
  using boost::simd::Minlog10;
  T ref = T(-308.2547155599167);

  STF_TYPE_IS(decltype(Minlog10<T>()), T);
  STF_IEEE_EQUAL(Minlog10<T>(), ref);
  STF_IEEE_EQUAL(minlog10( as(T{}) ), ref);
}

STF_CASE_TPL( "Check minlog10 behavior for float"
            , (float)
            )
{
  using boost::simd::as;
  using boost::simd::detail::minlog10;
  using boost::simd::Minlog10;
  T ref = T(-37.89999771118164);
  STF_TYPE_IS(decltype(Minlog10<T>()), T);
  STF_IEEE_EQUAL(Minlog10<T>(), ref);
  STF_IEEE_EQUAL(minlog10( as(T{}) ), ref);
}


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\
|  Phycas: Python software for phylogenetic analysis						  |
|  Copyright (C) 2006 Mark T. Holder, Paul O. Lewis and David L. Swofford	  |
|																			  |
|  This program is free software; you can redistribute it and/or modify		  |
|  it under the terms of the GNU General Public License as published by		  |
|  the Free Software Foundation; either version 2 of the License, or		  |
|  (at your option) any later version.										  |
|																			  |
|  This program is distributed in the hope that it will be useful,			  |
|  but WITHOUT ANY WARRANTY; without even the implied warranty of			  |
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the			  |
|  GNU General Public License for more details.								  |
|																			  |
|  You should have received a copy of the GNU General Public License along	  |
|  with this program; if not, write to the Free Software Foundation, Inc.,	  |
|  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.				  |
\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#if ! defined(TIP_DATA_HPP)
#define TIP_DATA_HPP

#include <vector>

#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>

#include "ncl/nxsallocatematrix.h"

#include "states_patterns.hpp"
#include "partition_model.hpp"

struct CIPRES_Matrix;

namespace CipresNative
{
class DiscreteMatrix;
}

namespace phycas
{
class TreeLikelihood;
class CondLikelihood;
class CondLikelihoodStorage;
typedef boost::shared_ptr<CondLikelihood> CondLikelihoodShPtr;
typedef boost::shared_ptr<const CondLikelihood> ConstCondLikelihoodShPtr;
class Tree;

/*----------------------------------------------------------------------------------------------------------------------
|	The TipData class stores the data associated with each tip in the tree. The description below assumes the data was
|	read from the following NEXUS data file (ambig.nex):
|>
|	#nexus
|
|	begin data;
|	  dimensions ntax=4 nchar=5;
|	  format datatype=dna missing=? gap=-;
|	  matrix
|		taxon1 A ? T  G	   (CGT)
|		taxon2 A C - (AGT)	T
|		taxon3 A C -  N	   (AG)
|		taxon4 A C T  R		Y
|	  ;
|	end;
|>
|	Assume that a partition with 2 subsets is specified. The first subset comprises sites 1-3, and the second subset
|	comprises sites 4 and 5. The data in the above NEXUS file would be stored internally in the form of state codes:
|	states or state combinations are replaced with integers ranging from -1 to 9.
|>
|	taxon1	0 4	 3 2 6
|	taxon2	0 1 -1 7 3
|	taxon3	0 1 -1 5 8
|	taxon4	0 1	 3 8 9
|>
|	The global state list (TreeLikelihood::state_list) for both subsets begins by defining the four primary DNA states
|	(A, C, G, T) and the completely ambiguous state (?). Note that ? includes all four primary states as well as
|	the gap state. Each state is preceded by the number of elements in the state list required to define that state.
|	Thus, each primary state is preceded by 1 because only one integer element is required to define a primary state.
|	The ? state requires 5 elements - gap (-1), A (0), C (1), G (2), and T (3) - and is thus preceded by the number 5.
|	The state list for the second subset must define 4 partially-ambiguous states: (CGT), (AGT), R=(AG) and Y=(CT).
|>
|	state_list[0]:
|	   1 0 1 1 1 2 1 3 5 -1 0 1 2 3
|	     A   C   G   T    - A C G T
|
|	state_list[1]:
|	   1 0 1 1 1 2 1 3 5 -1 0 1 2 3 4 0 1 2 3 3 1 2 3 3 0 2 3 2 0 2 2 1 3
|	     A   C   G   T    - A C G T   A C G T   C G T   A G T   A G   C T
|>
|	The global state list position vector (TreeLikelihood::state_list_pos) specifies the offset into the global state
|	lists needed to access each state.
|>
|	  state_list_pos[0]: 0 2 4 6 8
|	  state_list_pos[1]: 0 2 4 6 8 14 19 23 27 30
|>
|	For large datasets with many different ambiguity combinations, the global state lists could grow quite large. Each
|	state code ends up being a row in the augmented transposed transition probability matrix used in computing
|	conditional likelihood arrays, and it could be quite inefficient if these augmented matrices had many unnecessary
|	rows. Thus, when a row in a global state list is copied to the tip of a tree, where it is used to compute likelihoods,
|	a translation is done into local state codes. The local codes are identical to the global codes for the primary states
|	and the state representing complete ambiguity, but may differ from the global codes for codes representing partial
|	ambiguities. To illustrate, consider taxon4 in the example. It has these states in the NEXUS data file:
|	  A	 C	T  R  Y
|	which translate to these global state codes:
|>
|	  TreeLikelihood::state_list[0]: 0 1 3
|	  TreeLikelihood::state_list[1]: 8 9
|>
|	When copied to a tip node in a tree, however, these codes become translated to
|>
|	  TipData::state_list[0]: 0 1 3
|	  TipData::state_list[1]: 5 6
|>
|	Global codes 8 and 9 have become local codes 5 and 6, respectively.
|
|	Note that the TipData constructors are private and thus TipData objects can only be created by the friend function
|	allocateTipData().
*/
class TipData
  : boost::noncopyable
	{
	friend class TreeLikelihood;
	friend class SimData;

	public:
													TipData(PartitionModelShPtr partition, const state_list_pos_vect_t & positions, const state_list_vect_t & states, CondLikelihoodStorageShPtr cla_storage);
													TipData(PartitionModelShPtr partition, CondLikelihoodStorageShPtr cla_storage);// this constructor only used for simulations
                                           	 		~TipData();

		const double * const * const *				getConstTransposedPMatrices(unsigned i) const;
		double * * *								getTransposedPMatrices(unsigned i);
		double * * *								getMutableTransposedPMatrices(unsigned i) const;
		const state_code_t *						getConstStateCodes(unsigned i) const;

		CondLikelihoodShPtr							getParentalCondLikePtr();
		ConstCondLikelihoodShPtr					getValidParentalCondLikePtr() const;

		bool										parentalCLAValid() const;
		bool										parentalCLACached() const;

        state_list_t & 								getTipStatesArray(unsigned i) {return state_codes.at(i);}
        const state_list_t &						getConstTipStatesArray(unsigned i) const {return state_codes.at(i);}
		const uint_vect_t &							getConstStateListPos(unsigned i) const;

		friend void									calcPMatTranspose(const TreeLikelihood & treeLikeInfo, const TipData & tipData, double edgeLength);

	private:

		//bool										parCLAValid;
		CondLikelihoodShPtr							parWorkingCLA;		/**< conditional likelihood array for parent and beyond (valid if it points to something, invalid otherwise) */
		CondLikelihoodShPtr							parCachedCLA;		/**< parental conditional likelihood array is stored here to make reverting MCMC moves cheap */

		state_code_t								state;				/**< Used in simulation to temporarily store the state for one character */
		state_list_pos_vect_t						state_list_pos;		/**< Vector of indices into the tip-specific `state_codes' array */
		state_list_vect_t							state_codes;		/**< Array of tip-specific state codes */
		std::vector< ScopedThreeDMatrix<double> >	pMatrixTranspose;	/**< pMatrixTranspose[s][r] is the transposed transition matrix for subset s and relative rate r */
		CondLikelihoodStorageShPtr					cla_pool;			/**< Source of CondLikelihood objects if needed */
	};

typedef boost::shared_ptr<TipData> TipDataShPtr;
typedef std::vector<TipDataShPtr> VecTipDataShPtr;

// *********************************************************************************
// ***** TipData inlines ***********************************************************
// *********************************************************************************

/*----------------------------------------------------------------------------------------------------------------------
|	Returns `parWorkingCLA' data member as a shared pointer to const CondLikelihood. If `parWorkingCLA' does not
|	currently point to anything, a CondLikelihood object is first retrieved from `cla_pool', so this function always
|	returns a shared pointer that actually points to something.
*/
inline ConstCondLikelihoodShPtr TipData::getValidParentalCondLikePtr() const
	{
	//PHYCAS_ASSERT(parCLAValid);
	//TipData * t = const_cast<TipData *>(this);
	//return t->getParentalCondLikePtr();
	PHYCAS_ASSERT(parWorkingCLA);
	return ConstCondLikelihoodShPtr(parWorkingCLA);
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Accessor function that returns the element of `pMatrixTranspose' (const) corresponding to subset `i'.
*/
inline const double * const * const * TipData::getConstTransposedPMatrices(
  unsigned i) const		/**< is the subset */
	{
	return pMatrixTranspose[i].ptr;
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Accessor function that returns the element of `pMatrixTranspose' (non-const) corresponding to subset `i'.
*/
inline double * * * TipData::getTransposedPMatrices(
  unsigned i)		/**< is the subset */
	{
	return pMatrixTranspose[i].ptr;
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Accessor function that returns the data member `pMatrixTranspose' (non-const).
*/
inline double * * * TipData::getMutableTransposedPMatrices(
  unsigned i)		/**< is the subset */
  const
	{
	return pMatrixTranspose[i].ptr;
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Accessor function that returns the address of the first element of the vector of state codes for subset i.
*/
inline const state_code_t * TipData::getConstStateCodes(
  unsigned i)		/**< is the subset */
  const
	{
	return &(state_codes[i][0]);
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Accessor function that returns the `state_list_pos' data member. The returned vector of unsigned values holds
|	the position of each particular coded state for this tip in the local `state_codes' vector for subset i.
*/
inline const uint_vect_t & TipData::getConstStateListPos(
  unsigned i) 		/**< is the subset */
  const
	{
	return state_list_pos[i];
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Returns true if `parWorkingCLA' data member actually points to something, which means that the parental CLA is
|	valid. Returns false if `parWorkingCLA' does not point to a CondLikelihood object.
*/
inline bool TipData::parentalCLAValid() const
	{
	return (bool)parWorkingCLA;
	}

/*----------------------------------------------------------------------------------------------------------------------
|	Returns true if `parCachedCLA' data member actually points to something, which means the working CLA has been cached
|	in case a revert of the current move is needed. Returns false if `parCachedCLA' does not point to a CondLikelihood
|	object.
*/
inline bool TipData::parentalCLACached() const
	{
	return (bool)parCachedCLA;
	}

} // namespace phycas

#endif