/*
@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)
 */

#include <boost/hana/assert.hpp>
#include <boost/hana/ext/std/integral_constant.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>

#include <cassert>
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>

#include <boost/mpl/if.hpp>
#include <boost/mpl/quote.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/equal.hpp>
using namespace boost::hana;

int main() {

{

//! [type]
// We "lift" the `int` type to a value, and the `std::add_pointer` metafunction
// to a regular function. Then, we can call that metafunction with a regular
// function call syntax.
constexpr auto t = type<int>;
constexpr auto add_pointer = metafunction<std::add_pointer>;
static_assert(add_pointer(t) == type<int*>, "");
//! [type]

//! [type_as_nullary_metafunction]
using T = decltype(t)::type;
static_assert(std::is_same<T, int>{}, "");
//! [type_as_nullary_metafunction]

}{

//! [type_sequence]
constexpr auto types = make<Tuple>(type<int>, type<char const>, type<void>);
static_assert(
    transform(types, metafunction<std::add_pointer>) ==
    make<Tuple>(type<int*>, type<char const*>, type<void*>)
, "");
//! [type_sequence]

}{

//! [tuple_t]
constexpr auto types = tuple_t<int, char const, void>;
static_assert(types == make<Tuple>(type<int>, type<char const>, type<void>), "");

static_assert(
    transform(types, metafunction<std::add_pointer>) ==
    tuple_t<int*, char const*, void*>
, "");
//! [tuple_t]

}{

//! [type_three_step_cumbersome]
static_assert(std::is_same<
    decltype(metafunction<std::add_pointer>(type<int>))::type,
    int*
>{}, "");
//! [type_three_step_cumbersome]

//! [type_three_step_alternative]
static_assert(std::is_same<
    std::add_pointer<int>::type,
    int*
>{}, "");
//! [type_three_step_alternative]

}{

//! [apply_to_all]
auto apply_to_all = [](auto sequences, auto f) {
    return transform(sequences, [=](auto sequence) {
        return transform(sequence, f);
    });
};

constexpr auto types = make<Tuple>(
    tuple_t<int, char>,
    tuple_t<void, std::string, double>
);

BOOST_HANA_CONSTANT_CHECK(
    apply_to_all(types, metafunction<std::add_pointer>) ==
    make<Tuple>(
        tuple_t<int*, char*>,
        tuple_t<void*, std::string*, double*>
    )
);
//! [apply_to_all]

}

}

namespace mpl = boost::mpl;
//! [apply_to_all_mpl]
template <typename Sequences, typename F>
struct apply_to_all
    : mpl::transform<
        Sequences,
        mpl::transform<mpl::_1, F>
    >
{ };

using types = mpl::vector<
    mpl::vector<int, char>,
    mpl::vector<void, std::string, double>
>;

static_assert(mpl::equal<
    apply_to_all<types, mpl::quote1<std::add_pointer>>::type,
    mpl::vector<
        mpl::vector<int*, char*>,
        mpl::vector<void*, std::string*, double*>
    >,

    // mpl::equal was seemingly not designed for deep comparisons, so we
    // need this tricky line for it to do what we want.
    mpl::equal<mpl::_1, mpl::_2, mpl::quote2<std::is_same>>
>{}, "");
//! [apply_to_all_mpl]


/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2018 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "util/random.hpp"
#include "security/detail/openssl.hpp"

#include "boost-test.hpp"

#include <boost/mpl/vector.hpp>
#include <cmath>

namespace ndn {
namespace tests {

BOOST_AUTO_TEST_SUITE(Util)
BOOST_AUTO_TEST_SUITE(TestRandom)

class PseudoRandomWord32
{
public:
  static uint32_t
  generate()
  {
    return random::generateWord32();
  }
};

class PseudoRandomWord64
{
public:
  static uint64_t
  generate()
  {
    return random::generateWord64();
  }
};

class SecureRandomWord32
{
public:
  static uint32_t
  generate()
  {
    return random::generateSecureWord32();
  }
};

class SecureRandomWord64
{
public:
  static uint64_t
  generate()
  {
    return random::generateSecureWord64();
  }
};

typedef boost::mpl::vector<PseudoRandomWord32,
                           PseudoRandomWord64,
                           SecureRandomWord32,
                           SecureRandomWord64> RandomGenerators;

static double
getDeviation(const std::vector<uint32_t>& counts, size_t size)
{
  // Kolmogorov-Smirnov Goodness-of-Fit Test
  // http://www.itl.nist.gov/div898/handbook/eda/section3/eda35g.htm

  std::vector<double> edf(counts.size(), 0.0);
  double probability = 0.0;
  for (size_t i = 0; i < counts.size(); i++) {
    probability += 1.0 * counts[i] / size;
    edf[i] = probability;
  }

  double t = 0.0;
  for (size_t i = 0; i < counts.size(); i++) {
    t = std::max(t, std::abs(edf[i] - (i * 1.0 / counts.size())));
  }

  return t;
}

BOOST_AUTO_TEST_CASE_TEMPLATE(GoodnessOfFit, RandomGenerator, RandomGenerators)
{
  const size_t MAX_BINS = 32;
  const uint32_t MAX_ITERATIONS = 35;

  std::vector<uint32_t> counts(MAX_BINS, 0);

  for (uint32_t i = 0; i < MAX_ITERATIONS; i++) {
    counts[RandomGenerator::generate() % MAX_BINS]++;
  }

  // Check if it is uniform distribution with confidence 0.95
  // http://dlc.erieri.com/onlinetextbook/index.cfm?fuseaction=textbook.appendix&FileName=Table7
  BOOST_WARN_LE(getDeviation(counts, MAX_ITERATIONS), 0.230);
}

BOOST_AUTO_TEST_CASE(GenerateRandomBytes)
{
  // Kolmogorov-Smirnov Goodness-of-Fit Test
  // http://www.itl.nist.gov/div898/handbook/eda/section3/eda35g.htm

  uint8_t buf[1024] = {0};
  random::generateSecureBytes(buf, sizeof(buf));

  std::vector<uint32_t> counts(256, 0);

  for (size_t i = 0; i < sizeof(buf); i++) {
    counts[buf[i]]++;
  }

  // Check if it is uniform distribution with confidence 0.95
  // http://dlc.erieri.com/onlinetextbook/index.cfm?fuseaction=textbook.appendix&FileName=Table7
  BOOST_WARN_LE(getDeviation(counts, sizeof(buf)), 0.230);
}

// This fixture uses OpenSSL routines to set a dummy random generator that always fails
class FailRandMethodFixture
{
public:
  FailRandMethodFixture()
    : m_dummyRandMethod{&FailRandMethodFixture::seed,
                        &FailRandMethodFixture::bytes,
                        &FailRandMethodFixture::cleanup,
                        &FailRandMethodFixture::add,
                        &FailRandMethodFixture::pseudorand,
                        &FailRandMethodFixture::status}
  {
    m_origRandMethod = RAND_get_rand_method();
    RAND_set_rand_method(&m_dummyRandMethod);
  }

  ~FailRandMethodFixture()
  {
    RAND_set_rand_method(m_origRandMethod);
  }

private: // RAND_METHOD callbacks
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
  static void
  seed(const void* buf, int num)
  {
  }
#else
  static int
  seed(const void* buf, int num)
  {
    return 0;
  }
#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL

  static int
  bytes(unsigned char* buf, int num)
  {
    return 0;
  }

  static void
  cleanup()
  {
  }

#if OPENSSL_VERSION_NUMBER < 0x1010000fL
  static void
  add(const void* buf, int num, double entropy)
  {
  }
#else
  static int
  add(const void* buf, int num, double entropy)
  {
    return 0;
  }
#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL

  static int
  pseudorand(unsigned char* buf, int num)
  {
    return 0;
  }

  static int
  status()
  {
    return 0;
  }

private:
  const RAND_METHOD* m_origRandMethod;
  RAND_METHOD m_dummyRandMethod;
};

BOOST_FIXTURE_TEST_CASE(Error, FailRandMethodFixture)
{
  uint8_t buf[1024] = {0};
  BOOST_CHECK_THROW(random::generateSecureBytes(buf, sizeof(buf)), std::runtime_error);
}

BOOST_AUTO_TEST_SUITE_END() // TestRandom
BOOST_AUTO_TEST_SUITE_END() // Util

} // namespace tests
} // namespace ndn


// Boost.Geometry
// QuickBook Example

// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2015 Adam Wulkiewicz, Lodz, Poland.

// 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)

//[multi_linestring
//` Declaration and use of the Boost.Geometry model::multi_linestring, modelling the MultiLinestring Concept

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>

namespace bg = boost::geometry;

int main()
{
    typedef bg::model::point<double, 2, bg::cs::cartesian> point_t;
    typedef bg::model::linestring<point_t> linestring_t;
    typedef bg::model::multi_linestring<linestring_t> mlinestring_t;

    mlinestring_t mls1; /*< Default-construct a multi_linestring. >*/

#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) \
 && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)

    mlinestring_t mls2{{{0.0, 0.0}, {0.0, 1.0}, {2.0, 1.0}},
                       {{1.0, 0.0}, {2.0, 0.0}}}; /*< Construct a multi_linestring containing two linestrings, using C++11 unified initialization syntax. >*/

#endif

    mls1.resize(2); /*< Resize a multi_linestring, store two linestrings. >*/

    bg::append(mls1[0], point_t(0.0, 0.0)); /*< Append point to the first linestring. >*/
    bg::append(mls1[0], point_t(0.0, 1.0));
    bg::append(mls1[0], point_t(2.0, 1.0));

    bg::append(mls1[1], point_t(1.0, 0.0)); /*< Append point to the second linestring. >*/
    bg::append(mls1[1], point_t(2.0, 0.0));

    double l = bg::length(mls1);

    std::cout << l << std::endl;

    return 0;
}

//]

//[multi_linestring_output
/*`
Output:
[pre
4
]
*/
//]


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

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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_TEST_SIMPLIFY_HPP
#define BOOST_GEOMETRY_TEST_SIMPLIFY_HPP

// Test-functionality, shared between single and multi tests

#include <iomanip>
#include <sstream>
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/correct_closure.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/variant/variant.hpp>

template
<
    typename GeometryForTag,
    typename Tag = typename bg::tag<GeometryForTag>::type
>
struct test_equality
{
    template <typename Geometry, typename Expected>
    static void apply(Geometry const& geometry, Expected const& expected)
    {
        // Verify both spatially equal AND number of points, because several
        // of the tests only check explicitly on collinear points being
        // simplified away
        bool const result
                = bg::equals(geometry, expected)
                && bg::num_points(geometry) == bg::num_points(expected);

        BOOST_CHECK_MESSAGE(result,
                            " result: " << bg::wkt(geometry) << " " << bg::area(geometry)
                            << " expected: " << bg::wkt(expected) << " " << bg::area(expected));

    }
};

// Linestring does NOT yet have "geometry::equals" implemented
// Until then, WKT's are compared (which is acceptable for linestrings, but not
// for polygons, because simplify might rotate them)
template <typename GeometryForTag>
struct test_equality<GeometryForTag, bg::linestring_tag>
{
    template <typename Geometry, typename Expected>
    static void apply(Geometry const& geometry, Expected const& expected)
    {
        std::ostringstream out1, out2;
        out1 << bg::wkt(geometry);
        out2 << bg::wkt(expected);
        BOOST_CHECK_EQUAL(out1.str(), out2.str());
    }
};

template <typename Tag>
struct test_inserter
{
    template <typename Geometry, typename Expected>
    static void apply(Geometry& , Expected const& , double )
    {}
};

template <>
struct test_inserter<bg::linestring_tag>
{
    template <typename Geometry, typename Expected, typename DistanceMeasure>
    static void apply(Geometry& geometry,
            Expected const& expected,
            DistanceMeasure const& distance)
    {
        {
            Geometry simplified;
            bg::detail::simplify::simplify_insert(geometry,
                std::back_inserter(simplified), distance);

            test_equality<Geometry>::apply(simplified, expected);
        }

#ifdef TEST_PULL89
        {
            typedef typename bg::point_type<Geometry>::type point_type;
            typedef typename bg::strategy::distance::detail::projected_point_ax<>::template result_type<point_type, point_type>::type distance_type;
            typedef bg::strategy::distance::detail::projected_point_ax_less<distance_type> less_comparator;

            distance_type max_distance(distance);
            less_comparator less(max_distance);

            bg::strategy::simplify::detail::douglas_peucker
                <
                    point_type,
                    bg::strategy::distance::detail::projected_point_ax<>,
                    less_comparator
                > strategy(less);

            Geometry simplified;
            bg::detail::simplify::simplify_insert(geometry,
                std::back_inserter(simplified), max_distance, strategy);

            test_equality<Geometry>::apply(simplified, expected);
        }
#endif
    }
};

template <typename Geometry, typename Expected, typename DistanceMeasure>
void check_geometry(Geometry const& geometry,
                    Expected const& expected,
                    DistanceMeasure const& distance)
{
    Geometry simplified;
    bg::simplify(geometry, simplified, distance);
    test_equality<Expected>::apply(simplified, expected);
}

template <typename Geometry, typename Expected, typename Strategy, typename DistanceMeasure>
void check_geometry(Geometry const& geometry,
                    Expected const& expected,
                    DistanceMeasure const& distance,
                    Strategy const& strategy)
{
    Geometry simplified;
    bg::simplify(geometry, simplified, distance, strategy);
    test_equality<Expected>::apply(simplified, expected);
}

template <typename Geometry, typename DistanceMeasure>
void check_geometry_with_area(Geometry const& geometry,
                    double expected_area,
                    DistanceMeasure const& distance)
{
    Geometry simplified;
    bg::simplify(geometry, simplified, distance);
    BOOST_CHECK_CLOSE(bg::area(simplified), expected_area, 0.01);
}

template <typename Geometry, typename DistanceMeasure>
void test_geometry(std::string const& wkt,
        std::string const& expected_wkt,
        DistanceMeasure distance)
{
    typedef typename bg::point_type<Geometry>::type point_type;

    Geometry geometry, expected;

    bg::read_wkt(wkt, geometry);
    bg::read_wkt(expected_wkt, expected);

    boost::variant<Geometry> v(geometry);

    // Define default strategy for testing
    typedef bg::strategy::simplify::douglas_peucker
        <
            typename bg::point_type<Geometry>::type,
            bg::strategy::distance::projected_point<double>
        > dp;

    check_geometry(geometry, expected, distance);
    check_geometry(v, expected, distance);

    BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<dp, point_type>) );

    check_geometry(geometry, expected, distance, dp());
    check_geometry(v, expected, distance, dp());

    // Check inserter (if applicable)
    test_inserter
        <
            typename bg::tag<Geometry>::type
        >::apply(geometry, expected, distance);

#ifdef TEST_PULL89
    // Check using non-default less comparator in douglass_peucker
    typedef typename bg::strategy::distance::detail::projected_point_ax<>::template result_type<point_type, point_type>::type distance_type;
    typedef bg::strategy::distance::detail::projected_point_ax_less<distance_type> less_comparator;

    distance_type const max_distance(distance);
    less_comparator const less(max_distance);

    typedef bg::strategy::simplify::detail::douglas_peucker
        <
            point_type,
            bg::strategy::distance::detail::projected_point_ax<>,
            less_comparator
        > douglass_peucker_with_less;

    BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<douglass_peucker_with_less, point_type>) );

    check_geometry(geometry, expected, distance, douglass_peucker_with_less(less));
    check_geometry(v, expected, distance, douglass_peucker_with_less(less));
#endif
}

template <typename Geometry, typename Strategy, typename DistanceMeasure>
void test_geometry(std::string const& wkt,
        std::string const& expected_wkt,
        DistanceMeasure const& distance,
        Strategy const& strategy)
{
    Geometry geometry, expected;

    bg::read_wkt(wkt, geometry);
    bg::read_wkt(expected_wkt, expected);
    bg::correct_closure(geometry);
    bg::correct_closure(expected);

    boost::variant<Geometry> v(geometry);

    BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<Strategy,
                           typename bg::point_type<Geometry>::type>) );

    check_geometry(geometry, expected, distance, strategy);
    check_geometry(v, expected, distance, strategy);
}

template <typename Geometry, typename DistanceMeasure>
void test_geometry(std::string const& wkt,
        double expected_area,
        DistanceMeasure const& distance)
{
    Geometry geometry;
    bg::read_wkt(wkt, geometry);
    bg::correct_closure(geometry);

    check_geometry_with_area(geometry, expected_area, distance);
}

#endif


// Exercise 5.1.3 - Variant
//
// by Scott Sidoli
//
// 5-29-19
//
// Main.cpp
//
// In this exercise, we experiment with boost::variant. This is similar to tuple, but can only store one value.
// We create a function that asks the user for a kind of shape to create and then returns that shape. Instead of
// returning a Shape*, we return a boost::variant. We create a typedef 'ShapeType' that can contain a Point, Line,
// or Circle. In the main function we call the function and print the result. Next, we try to assign the variant
// to a Line variable by using the global boost::get<T>() function. We expect an exception to get thrown. Finally,
// we experiment with 'visitors'. We create a variant visitor that moves shapes, apply it, and print the shape
// afterwords to see if the shape's coordinates actually changed.

#include <boost\variant.hpp>
#include <iostream>
#include "Line.hpp"
#include "Circle.hpp"
#include "Visitor.hpp"
#include "Point.hpp"
#include <string>

using namespace std;
using namespace ssidoli::CAD;

typedef boost::variant<Point, Line, Circle> ShapeType;

ShapeType Create_Shape()
{
	ShapeType shape;

	cout << "Please choose a shape: " << endl << "a) Point" << endl << "b) Line" << endl << "c) Circle" << endl;
	char choice;
	cin >> choice;

	switch (choice)
	{
	case 'a':
		shape = Point();
		break;

	case 'b':
		shape = Line();
		break;

	case 'c':
		shape = Circle();
		break;

	default:
		break;
	}

	return shape;
}

int main()
{
	using boost::variant;

	// Creating a shape
	ShapeType user_Shape = Create_Shape();
	cout << "before visiting: " << user_Shape << endl;

	// Trying to catch an exception
	try
	{
		Line l = boost::get<Line>(user_Shape);
	}

	catch (boost::bad_get& ex)
	{
		cout << "Error: " << ex.what() << endl;
	}

	// Using Visitor
	Visitor visitor(5.0, 7.0);
	boost::apply_visitor(visitor, user_Shape);

	cout << "After visiting: " << user_Shape << endl;
	return 0;
}

Scott_Sidoli Level 8 HW Submission/Section 5.1/Exercise513/Exercise513/Main.cpp


//C++ implementation code of finding the product of large numbers using Boost Lib.
//The Boost.Multiprecision library can be used for computations requiring precision exceeding that of standard built-in types such as float, double and long double.
//For extended-precision calculations, Boost.Multiprecision supplies a template data type called cpp_dec_float.

#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision; //here we are using boost as namespace that includes boost libarary
using namespace std;

//the below line is the function where the product of two numbers will take place.
int128_t boost_product(long long A, long long B)
{
    int128_t ans = (int128_t) A * B;
    return ans;
}

//in main function we tooked two long data type numbers and then called our boost_product() function.
int main()
{
    long long first = 98745636214564698;
    long long second=7459874565236544789;
    cout << "Product of "<< first << " * "
         << second << " = \n"
         << boost_product(first,second) ;
    return 0;
}


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

#include <boost/test/unit_test.hpp>

#include "utils.h"
#include "tsl/uint_n.h"

template <size_t BITS_COUNT>
using uint_n = tsl::uint_n<BITS_COUNT, uint8_t>;

BOOST_AUTO_TEST_SUITE(test_bitset)

namespace {

template <size_t N>
std::string to_string(uint_n<N> const& x) {
    std::ostringstream oss;
    oss << x;
    return oss.str();
}

} // namespace

BOOST_AUTO_TEST_CASE(test_constructor_from_int) {
    uint_n<2> x(1);
    BOOST_CHECK_EQUAL(to_string(x), "01");
}

BOOST_AUTO_TEST_CASE(test_constructor_from_multiple_int) {
    uint_n<9> x(1_b, 101_b);
    BOOST_CHECK_EQUAL(to_string(x), "1'00000101");
}

BOOST_AUTO_TEST_CASE(test_shift_left_operator) {
    {
        uint_n<1> x(1);
        x <<= 1;
        BOOST_CHECK_EQUAL(to_string(x), "0");
    }

    {
        uint_n<2> x(01_b);
        x <<= 1;
        BOOST_CHECK_EQUAL(to_string(x), "10");
    }

    {
        uint_n<10> x(00000000_b, 10101001_b);
        x <<= 3;
        BOOST_CHECK_EQUAL(to_string(x), "01'01001000");
    }

    {
        uint_n<10> x(00000000_b, 10101001_b);
        x <<= 3;
        BOOST_CHECK_EQUAL(to_string(x), "01'01001000");
    }

    {
        uint_n<32> x(00000000_b, 10101001_b, 00001000_b, 00000100_b);
        x <<= 9;
        BOOST_CHECK_EQUAL(to_string(x), "01010010'00010000'00001000'00000000");
    }
}

BOOST_AUTO_TEST_CASE(test_operator_pre_decrement) {
    {
        uint_n<1> x(1_b);
        --x;
        BOOST_CHECK_EQUAL(to_string(x), "0");
        --x;
        BOOST_CHECK_EQUAL(to_string(x), "1");
    }

    {
        uint_n<10> x(1_b, 1_b);
        --x;
        BOOST_CHECK_EQUAL(to_string(x), "01'00000000");
        --x;
        BOOST_CHECK_EQUAL(to_string(x), "00'11111111");
    }

    {
        uint_n<9> x(0_b, 0_b);
        --x;
        BOOST_CHECK_EQUAL(to_string(x), "1'11111111");
    }
}

BOOST_AUTO_TEST_CASE(test_popcount) {
    BOOST_CHECK_EQUAL(popcount(uint_n<1>(0_b)), 0);
    BOOST_CHECK_EQUAL(popcount(uint_n<1>(1_b)), 1);
    BOOST_CHECK_EQUAL(popcount(uint_n<2>(11_b)), 2);
    BOOST_CHECK_EQUAL(popcount(uint_n<2>(111_b)), 2);
    BOOST_CHECK_EQUAL(popcount(uint_n<9>(1_b, 1_b)), 2);
}

BOOST_AUTO_TEST_CASE(test_operator_bitwise_and) {
    {
        uint_n<1> x(1_b);
        const uint_n<1> y(1_b);
        BOOST_CHECK_EQUAL(to_string(x &= y), "1");
    }

    {
        uint_n<1> x(0_b);
        const uint_n<1> y(1_b);
        BOOST_CHECK_EQUAL(to_string(x &= y), "0");
    }

    {
        uint_n<10> x(10_b, 111_b);
        const uint_n<10> y(11_b, 101_b);
        BOOST_CHECK_EQUAL(to_string(x &= y), "10'00000101");
    }

}

BOOST_AUTO_TEST_CASE(test_test) {
    {
        const uint_n<1> x(1_b);
        BOOST_CHECK(x.test(0));
    }

    {
        const uint_n<1> x(0_b);
        BOOST_CHECK(!x.test(0));
    }

    {
        const uint_n<11> x(101_b, 10010000_b);
        BOOST_CHECK(x.test(10));
        BOOST_CHECK(!x.test(9));
        BOOST_CHECK(x.test(8));
        BOOST_CHECK(x.test(7));
        BOOST_CHECK(!x.test(6));
        BOOST_CHECK(x.test(4));
        BOOST_CHECK(!x.test(3));
    }
}

BOOST_AUTO_TEST_CASE(test_set) {
    uint_n<11> x{};
    x.set(1);
    x.set(3);
    x.set(7);
    x.set(10);
    x.set(10);
    BOOST_CHECK_EQUAL(to_string(x), "100'10001010");
}

BOOST_AUTO_TEST_CASE(test_unset) {
    uint_n<11> x(101_b, 10001010_b);
    x.unset(0);
    x.unset(1);
    x.unset(8);
    BOOST_CHECK_EQUAL(to_string(x), "100'10001000");
}

BOOST_AUTO_TEST_SUITE_END()


/** @file cpp_int_util.hpp Supports the use of Boost cpp_int. */

#ifndef INCLUDED_CPP_INT_UTIL
#define INCLUDED_CPP_INT_UTIL

/// @cond
#include <boost/multiprecision/cpp_int.hpp> // cpp_int

// TODO cassert
#include <algorithm>                        // count
#include <climits>                          // CHAR_MAX
#include <cstdlib>                          // size_t
#include <string>                           // string
/// @endcond

namespace cpp_int_util {

using boost::multiprecision::cpp_int;

/** STL-compatible hash functor for use with unordered containers. */
struct hash {
    std::size_t operator()(cpp_int const& n) const;
};

int sum_digits(cpp_int const& n);

}

inline
std::size_t cpp_int_util::hash::operator()(cpp_int const& n) const {
    return n.convert_to<std::size_t>();
}

template<>
struct std::hash<boost::multiprecision::cpp_int>: cpp_int_util::hash { };

#endif


/*
 [auto_generated]
 libs/numeric/odeint/test/adaptive_iterator.cpp

 [begin_description]
 This file tests the adaptive iterators.
 [end_description]

 Copyright 2012-2013 Karsten Ahnert
 Copyright 2012-2013 Mario Mulansky

 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)
 */

#define BOOST_TEST_MODULE odeint_adaptive_iterator

#include <iterator>
#include <algorithm>
#include <vector>

#include <boost/numeric/odeint/config.hpp>
#include <boost/array.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/mpl/vector.hpp>

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

#include <boost/numeric/odeint/iterator/adaptive_iterator.hpp>
#include "dummy_steppers.hpp"
#include "dummy_odes.hpp"
#include "dummy_observers.hpp"

namespace mpl = boost::mpl;
using namespace boost::numeric::odeint;

typedef dummy_stepper::state_type state_type;
typedef dummy_stepper::value_type value_type;

BOOST_AUTO_TEST_SUITE( adaptive_iterator_test )

typedef mpl::vector<
    dummy_controlled_stepper
    , dummy_dense_output_stepper
    > dummy_steppers;

BOOST_AUTO_TEST_CASE( copy_controlled_stepper_iterator )
{
    typedef adaptive_iterator< dummy_controlled_stepper , empty_system , state_type > iterator_type;

    state_type x = {{ 1.0 }};
    iterator_type iter1( dummy_controlled_stepper() , empty_system() , x );
    iterator_type iter2( iter1 );

    BOOST_CHECK_EQUAL( &( *iter1 ) , &x );
    BOOST_CHECK_EQUAL( &( *iter2 ) , &x );
    BOOST_CHECK_EQUAL( &( *iter1 ) , &( *iter2 ) );
    BOOST_CHECK( iter1.same( iter2 ) );

    ++iter1;
    ++iter2;

    BOOST_CHECK_EQUAL( &( *iter1 ) , &x );
    BOOST_CHECK_EQUAL( &( *iter2 ) , &x );
    BOOST_CHECK_EQUAL( &( *iter1 ) , &( *iter2 ) );
    BOOST_CHECK( iter1.same( iter2 ) );

}

BOOST_AUTO_TEST_CASE( copy_dense_output_stepper_iterator )
{
    typedef adaptive_iterator< dummy_dense_output_stepper , empty_system , state_type > iterator_type;

    state_type x = {{ 1.0 }};
    // fix by mario: do not dereference iterators at the end - made iter1 start iterator
    iterator_type iter1( dummy_dense_output_stepper() , empty_system() , x , 0.0 , 1.0 , 0.1 );
    iterator_type iter2( iter1 );

    // fix by mario: iterator dereference now always gives internal state also for dense output, consistent with other iterator implementations
    // changed: iterators with dense output stepper do not have an internal state now to avoid a copy
    BOOST_CHECK_NE( & (*iter1) , & (*iter2) );
    BOOST_CHECK( iter1.same( iter2 ) );

    ++iter1;
    ++iter2;

    BOOST_CHECK_NE( & (*iter1) , & (*iter2) );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE( copy_dense_output_stepper_iterator_with_reference_wrapper )
{
    // bad use case, the same stepper is iterated twice
    typedef adaptive_iterator< boost::reference_wrapper< dummy_dense_output_stepper > , empty_system , state_type > iterator_type;

    state_type x = {{ 1.0 }};
    dummy_dense_output_stepper stepper;
    iterator_type iter1( boost::ref( stepper ) , empty_system() , x , 0.0 , 0.9 , 0.1 );
    iterator_type iter2( iter1 );

    BOOST_CHECK_EQUAL( & (*iter1) , & (*iter2) );
    BOOST_CHECK( iter1.same( iter2 ) );

    ++iter1;
    ++iter2;

    BOOST_CHECK_EQUAL( & (*iter1) , & (*iter2) );
    BOOST_CHECK( !iter1.same( iter2 ) );         // they point to the same stepper, there the times will be different
}

BOOST_AUTO_TEST_CASE( assignment_controlled_stepper_iterator )
{
    typedef adaptive_iterator< dummy_controlled_stepper , empty_system , state_type > iterator_type;
    state_type x1 = {{ 1.0 }} , x2 = {{ 2.0 }};
    iterator_type iter1 = iterator_type( dummy_controlled_stepper() , empty_system() , x1 , 0.0 , 1.0 , 0.1 );
    iterator_type iter2 = iterator_type( dummy_controlled_stepper() , empty_system() , x2 , 0.0 , 1.0 , 0.2 );
    BOOST_CHECK_EQUAL( &(*iter1) , &x1 );
    BOOST_CHECK_EQUAL( &(*iter2) , &x2 );
    // the iterators are indeed the same as this only checks the time values
    BOOST_CHECK( !iter1.same( iter2 ) );
    iter2 = iter1;
    BOOST_CHECK_EQUAL( &(*iter1) , &x1 );
    BOOST_CHECK_EQUAL( &(*iter2) , &x1 );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE( assignment_dense_output_stepper_iterator )
{
    typedef adaptive_iterator< dummy_dense_output_stepper , empty_system , state_type > iterator_type;
    state_type x1 = {{ 1.0 }};
    iterator_type iter1 = iterator_type( dummy_dense_output_stepper() , empty_system() , x1 , 0.0 , 1.0 , 0.1 );
    iterator_type iter2 = iterator_type( dummy_dense_output_stepper() , empty_system() , x1 , 0.0 , 1.0 , 0.2 );

    BOOST_CHECK_NE( & (*iter1) , & (*iter2) );
    BOOST_CHECK( !iter1.same( iter2 ) );

    iter2 = iter1;
    // fix by mario: iterator dereference now always gives internal state also for dense output, consistent with other iterator implementations
    // changed: iterators with dense output stepper do not have an internal state now to avoid a copy
    BOOST_CHECK_NE( & (*iter1) , & (*iter2) );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE( assignment_dense_output_stepper_iterator_with_reference_wrapper )
{
    typedef adaptive_iterator< boost::reference_wrapper< dummy_dense_output_stepper > , empty_system , state_type > iterator_type;
    state_type x1 = {{ 1.0 }};

    dummy_dense_output_stepper stepper;
    iterator_type iter1 = iterator_type( boost::ref( stepper )  , empty_system() , x1 , 0.0 , 1.0 , 0.1 );
    iterator_type iter2 = iterator_type( boost::ref( stepper ) , empty_system() , x1 , 0.0 , 1.0 , 0.2 );

    BOOST_CHECK_EQUAL( & (*iter1) , & (*iter2) );
    BOOST_CHECK( !iter1.same( iter2 ) );

    iter2 = iter1;

    BOOST_CHECK_EQUAL( & (*iter1) , & (*iter2) );
    BOOST_CHECK( iter1.same( iter2 ) );
}

BOOST_AUTO_TEST_CASE( controlled_stepper_iterator_factory )
{
    dummy_controlled_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
         make_adaptive_iterator_begin( stepper , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
         make_adaptive_iterator_end( stepper , boost::ref( system ) , x ) ,
         dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-14 );
}

// just test if it compiles
BOOST_AUTO_TEST_CASE( dense_output_stepper_iterator_factory )
{
    dummy_dense_output_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
         make_adaptive_iterator_begin( stepper , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
         make_adaptive_iterator_end( stepper , boost::ref( system ) , x ) ,
         dummy_observer() );
}

BOOST_AUTO_TEST_CASE( controlled_stepper_range )
{
    dummy_controlled_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_adaptive_range( stepper , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
                     dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-14 );
}

// just test if it compiles
BOOST_AUTO_TEST_CASE( dense_output_stepper_range )
{
    dummy_dense_output_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_adaptive_range( stepper , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
                     dummy_observer() );
}

BOOST_AUTO_TEST_CASE( controlled_stepper_iterator_with_reference_wrapper_factory )
{
    dummy_controlled_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
        make_adaptive_iterator_begin( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
        make_adaptive_iterator_end( boost::ref( stepper ) , boost::ref( system ) , x ) ,
        dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-14 );
}

// just test if it compiles
BOOST_AUTO_TEST_CASE( dense_output_stepper_iterator_with_reference_wrapper_factory )
{
    dummy_dense_output_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    std::for_each(
        make_adaptive_iterator_begin( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
        make_adaptive_iterator_end( boost::ref( stepper ) , boost::ref( system ) , x ) ,
        dummy_observer() );
}

BOOST_AUTO_TEST_CASE( controlled_stepper_range_with_reference_wrapper )
{
    dummy_controlled_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_adaptive_range( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
                     dummy_observer() );

    BOOST_CHECK_CLOSE( x[0] , 3.5 , 1.0e-14 );
}

// just test if it compiles
BOOST_AUTO_TEST_CASE( dense_output_stepper_range_with_reference_wrapper )
{
    dummy_dense_output_stepper stepper;
    empty_system system;
    state_type x = {{ 1.0 }};

    boost::for_each( make_adaptive_range( boost::ref( stepper ) , boost::ref( system ) , x , 0.0 , 1.0 , 0.1 ) ,
                     dummy_observer() );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( transitivity1 , Stepper , dummy_steppers )
{
    typedef adaptive_iterator< Stepper , empty_system , state_type > stepper_iterator;

    state_type x = {{ 1.0 }};
    stepper_iterator first1( Stepper() , empty_system() , x , 2.5 , 2.0 , 0.1 );
    stepper_iterator last1( Stepper() , empty_system() , x );
    stepper_iterator last2( Stepper() , empty_system() , x );

    BOOST_CHECK( first1 == last1 );
    BOOST_CHECK( first1 == last2 );
    BOOST_CHECK( last1 == last2 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm , Stepper , dummy_steppers )
{
    typedef adaptive_iterator< Stepper , empty_system , state_type > stepper_iterator;
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    stepper_iterator first( Stepper() , empty_system() , x , 0.0 , 0.35 , 0.1 );
    stepper_iterator last( Stepper() , empty_system() , x );

    std::copy( first , last , std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 5 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[4][0] , 2.0 , 1.0e-14 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm_with_factory , Stepper , dummy_steppers )
{
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    std::copy( make_adaptive_iterator_begin( Stepper() , empty_system() , x , 0.0 , 0.35 , 0.1 ) ,
               make_adaptive_iterator_end( Stepper() , empty_system() , x ) ,
               std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 5 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[4][0] , 2.0 , 1.0e-14 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( copy_algorithm_with_range_factory , Stepper , dummy_steppers )
{
    state_type x = {{ 1.0 }};
    std::vector< state_type > res;
    boost::range::copy( make_adaptive_range( Stepper() , empty_system() , x , 0.0 , 0.35 , 0.1 ) ,
                        std::back_insert_iterator< std::vector< state_type > >( res ) );

    BOOST_CHECK_EQUAL( res.size() , size_t( 5 ) );
    BOOST_CHECK_CLOSE( res[0][0] , 1.0 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[1][0] , 1.25 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[2][0] , 1.5 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[3][0] , 1.75 , 1.0e-14 );
    BOOST_CHECK_CLOSE( res[4][0] , 2.0 , 1.0e-14 );
}

BOOST_AUTO_TEST_SUITE_END()


//
// Created by przemek on 01.04.2020.
//
#include <AST/expression/base_math_expr.h>
#include <AST/expression/realtion_expr.h>
#include <AST/statement/assign_stmt.h>
#include <AST/statement/if_stmt.h>
#include <AST/statement/return_stmt.h>
#include <boost/test/unit_test.hpp>
#include <mock_expr.h>
#include <mock_stmt.h>

using namespace vecc;
using namespace vecc::ast;
using namespace vecc::test;

BOOST_AUTO_TEST_SUITE(AST_Test_Suite)

BOOST_AUTO_TEST_SUITE(If_Stmt_Test_Suite)

BOOST_AUTO_TEST_CASE(IfTest_NoThrow) {
  auto cond = std::make_unique<BaseMathExpr>(Variable());

  IfStatement ifStmt(std::move(cond));

  Return temp;
  BOOST_CHECK_NO_THROW(temp = ifStmt.run());
}

BOOST_AUTO_TEST_CASE(IfTrueTest_TrueBlockRun) {
  auto var1 = Variable({1});
  auto var2 = Variable({10});
  auto cond = std::make_unique<RelationExpr>(
      std::make_unique<BaseMathExpr>(&var1), RelationExpr::OperatorType::Less,
      std::make_unique<BaseMathExpr>(&var2));

  IfStatement ifStmt(std::move(cond));

  ifStmt.falseBlock().addInstruction(std::make_unique<AssignStatement>(
      var2, std::make_unique<BaseMathExpr>(Variable({99}))));

  ifStmt.trueBlock().addInstruction(std::make_unique<AssignStatement>(
      var1, std::make_unique<BaseMathExpr>(Variable({99}))));

  BOOST_CHECK_EQUAL(true, ifStmt.run().type_ == Return::Type::Noting);
  BOOST_CHECK_EQUAL(var1, Variable({99}));
  BOOST_CHECK_EQUAL(var2, Variable({10}));
}

BOOST_AUTO_TEST_CASE(IfFalseTest_FalseBlockRun) {
  auto var1 = Variable({1});
  auto var2 = Variable({10});
  auto cond =
      std::make_unique<RelationExpr>(std::make_unique<BaseMathExpr>(&var1),
                                     RelationExpr::OperatorType::GreaterOrEqual,
                                     std::make_unique<BaseMathExpr>(&var2));

  IfStatement ifStmt(std::move(cond));

  ifStmt.falseBlock().addInstruction(std::make_unique<AssignStatement>(
      var2, std::make_unique<BaseMathExpr>(Variable({99}))));

  ifStmt.trueBlock().addInstruction(std::make_unique<AssignStatement>(
      var1, std::make_unique<BaseMathExpr>(Variable({99}))));

  BOOST_CHECK_EQUAL(true, ifStmt.run().type_ == Return::Type::Noting);
  BOOST_CHECK_EQUAL(var1, Variable({1}));
  BOOST_CHECK_EQUAL(var2, Variable({99}));
}

BOOST_AUTO_TEST_CASE(IfTrueTest_TrueBlockReturn) {
  auto cond = std::make_unique<BaseMathExpr>(Variable({1}));

  BOOST_REQUIRE_EQUAL(true, cond->calculate());

  IfStatement ifStmt(std::move(cond));

  ifStmt.trueBlock().addInstruction(std::make_unique<ReturnStatement>(
      std::make_unique<BaseMathExpr>(Variable({99}))));

  ifStmt.falseBlock().addInstruction(std::make_unique<ReturnStatement>(
      std::make_unique<BaseMathExpr>(Variable({22}))));

  BOOST_CHECK_EQUAL(true, ifStmt.run().type_ == Return::Type::Value);
  BOOST_CHECK_EQUAL(ifStmt.run().variable_, Variable({99}));
}

BOOST_AUTO_TEST_CASE(IfFalseTest_FalseBlockReturn) {
  auto cond = std::make_unique<BaseMathExpr>(Variable({0}));

  BOOST_REQUIRE_EQUAL(false, cond->calculate());

  IfStatement ifStmt(std::move(cond));

  ifStmt.trueBlock().addInstruction(std::make_unique<ReturnStatement>(
      std::make_unique<BaseMathExpr>(Variable({99}))));

  ifStmt.falseBlock().addInstruction(std::make_unique<ReturnStatement>(
      std::make_unique<BaseMathExpr>(Variable({22}))));

  BOOST_CHECK_EQUAL(true, ifStmt.run().type_ == Return::Type::Value);
  BOOST_CHECK_EQUAL(ifStmt.run().variable_, Variable({22}));
}

BOOST_AUTO_TEST_CASE(If_ToStringWorks) {
  IfStatement ifStmt(std::make_unique<MockExpr>("condition"));

  ifStmt.trueBlock().addInstruction(std::make_unique<MockStmt>("true block"));

  ifStmt.falseBlock().addInstruction(std::make_unique<MockStmt>("false block"));

  BOOST_CHECK_EQUAL(ifStmt.toString(),
                    "if(condition){\ntrue block;\n}else{\nfalse block;\n}");
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()


//////////////////////////////////////////////////////////////////////////////
///   Copyright 2003 and onward LASMEA UMR 6602 CNRS/U.B.P Clermont-Ferrand
///   Copyright 2009 and onward LRI    UMR 8623 CNRS/Univ Paris Sud XI
///
///          Distributed under the Boost Software License, Version 1.0
///                 See accompanying file LICENSE.txt or copy at
///                     http://www.boost.org/LICENSE_1_0.txt
//////////////////////////////////////////////////////////////////////////////
#define NT2_UNIT_MODULE "nt2 bitwise toolbox - ffs/scalar Mode"

//////////////////////////////////////////////////////////////////////////////
// Test behavior of bitwise components in scalar mode
//////////////////////////////////////////////////////////////////////////////
/// created  by jt the 18/02/2011
/// modified by jt the 16/03/2011
#include <boost/type_traits/is_same.hpp>
#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/unit/tests.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <nt2/sdk/memory/buffer.hpp>
#include <nt2/sdk/constant/real.hpp>
#include <nt2/sdk/constant/infinites.hpp>
#include <nt2/include/functions/ulpdist.hpp>
#include <nt2/toolbox/bitwise/include/ffs.hpp>

NT2_TEST_CASE_TPL ( ffs_float_1,  (float))
{

  using nt2::ffs;
  using nt2::tag::ffs_;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::call<ffs_(T)>::type r_t;
  typedef typename nt2::meta::upgrade<T>::type u_t;
  typedef typename nt2::meta::as_integer<T, unsigned>::type wished_r_t;

  // return type conformity test
  NT2_TEST( (boost::is_same < r_t, wished_r_t >::value) );
  std::cout << std::endl;
  double ulpd;
  ulpd=0.0;

  // specific values tests
  NT2_TEST_EQUAL(ffs(nt2::Inf<T>()), 24u);
  NT2_TEST_EQUAL(ffs(nt2::Minf<T>()), 24u);
  NT2_TEST_EQUAL(ffs(nt2::Nan<T>()), nt2::One<r_t>());
  NT2_TEST_EQUAL(ffs(nt2::Signmask<T>()), sizeof(T)*8);
  NT2_TEST_EQUAL(ffs(nt2::Zero<T>()), nt2::Zero<r_t>());
} // end of test for float

NT2_TEST_CASE_TPL ( ffs_double_1,  (double))
{

  using nt2::ffs;
  using nt2::tag::ffs_;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::call<ffs_(T)>::type r_t;
  typedef typename nt2::meta::upgrade<T>::type u_t;
  typedef typename nt2::meta::as_integer<T, unsigned>::type wished_r_t;

  // return type conformity test
  NT2_TEST( (boost::is_same < r_t, wished_r_t >::value) );
  std::cout << std::endl;
  double ulpd;
  ulpd=0.0;

  // specific values tests
  NT2_TEST_EQUAL(ffs(nt2::Inf<T>()), 53u);
  NT2_TEST_EQUAL(ffs(nt2::Minf<T>()), 53u);
  NT2_TEST_EQUAL(ffs(nt2::Nan<T>()), nt2::One<r_t>());
  NT2_TEST_EQUAL(ffs(nt2::Signmask<T>()), sizeof(T)*8);
  NT2_TEST_EQUAL(ffs(nt2::Zero<T>()), nt2::Zero<r_t>());
} // end of test for double

NT2_TEST_CASE_TPL ( ffs_signed_int__1,  NT2_INTEGRAL_SIGNED_TYPES)
{

  using nt2::ffs;
  using nt2::tag::ffs_;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::call<ffs_(T)>::type r_t;
  typedef typename nt2::meta::upgrade<T>::type u_t;
  typedef typename nt2::meta::as_integer<T, unsigned>::type wished_r_t;

  // return type conformity test
  NT2_TEST( (boost::is_same < r_t, wished_r_t >::value) );
  std::cout << std::endl;
  double ulpd;
  ulpd=0.0;

  // specific values tests
  NT2_TEST_EQUAL(ffs(nt2::One<T>()), nt2::One<r_t>());
  NT2_TEST_EQUAL(ffs(nt2::Signmask<T>()), sizeof(T)*8);
  NT2_TEST_EQUAL(ffs(nt2::Zero<T>()), nt2::Zero<r_t>());
} // end of test for signed_int_

NT2_TEST_CASE_TPL ( ffs_unsigned_int__1,  NT2_UNSIGNED_TYPES)
{

  using nt2::ffs;
  using nt2::tag::ffs_;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::call<ffs_(T)>::type r_t;
  typedef typename nt2::meta::upgrade<T>::type u_t;
  typedef typename nt2::meta::as_integer<T, unsigned>::type wished_r_t;

  // return type conformity test
  NT2_TEST( (boost::is_same < r_t, wished_r_t >::value) );
  std::cout << std::endl;
  double ulpd;
  ulpd=0.0;

  // specific values tests
  NT2_TEST_EQUAL(ffs(nt2::One<T>()), nt2::One<r_t>());
  NT2_TEST_EQUAL(ffs(nt2::Zero<T>()), nt2::Zero<r_t>());
} // end of test for unsigned_int_


//  Copyright (c) 2015 Hartmut Kaiser
//
//  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 <hpx/hpx_init.hpp>
#include <hpx/hpx.hpp>
#include <hpx/include/parallel_set_operations.hpp>
#include <hpx/util/lightweight_test.hpp>

#include <boost/range/functions.hpp>

#include "test_utils.hpp"

///////////////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference1(ExPolicy const& policy, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::test_iterator<base_iterator, IteratorTag> iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size()), c4(2*c1.size());

    hpx::parallel::set_symmetric_difference(policy,
        iterator(boost::begin(c1)), iterator(boost::end(c1)),
        boost::begin(c2), boost::end(c2), boost::begin(c3));

    std::set_symmetric_difference(boost::begin(c1), boost::end(c1),
        boost::begin(c2), boost::end(c2), boost::begin(c4));

    // verify values
    HPX_TEST(std::equal(boost::begin(c3), boost::end(c3), boost::begin(c4)));
}

template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference1_async(ExPolicy const& p, IteratorTag)
{
    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::test_iterator<base_iterator, IteratorTag> iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size()), c4(2*c1.size());

    hpx::future<void> result =
        hpx::parallel::set_symmetric_difference(p,
            iterator(boost::begin(c1)), iterator(boost::end(c1)),
            boost::begin(c2), boost::end(c2), boost::begin(c3));
    result.wait();

    std::set_symmetric_difference(boost::begin(c1), boost::end(c1),
        boost::begin(c2), boost::end(c2), boost::begin(c4));

    // verify values
    HPX_TEST(std::equal(boost::begin(c3), boost::end(c3), boost::begin(c4)));
}

template <typename IteratorTag>
void test_set_symmetric_difference1()
{
    using namespace hpx::parallel;

    test_set_symmetric_difference1(seq, IteratorTag());
    test_set_symmetric_difference1(par, IteratorTag());
    test_set_symmetric_difference1(par_vec, IteratorTag());

    test_set_symmetric_difference1_async(seq(task), IteratorTag());
    test_set_symmetric_difference1_async(par(task), IteratorTag());

    test_set_symmetric_difference1(execution_policy(seq), IteratorTag());
    test_set_symmetric_difference1(execution_policy(par), IteratorTag());
    test_set_symmetric_difference1(execution_policy(par_vec), IteratorTag());

    test_set_symmetric_difference1(execution_policy(seq(task)), IteratorTag());
    test_set_symmetric_difference1(execution_policy(par(task)), IteratorTag());
}

void set_symmetric_difference_test1()
{
    test_set_symmetric_difference1<std::random_access_iterator_tag>();
    test_set_symmetric_difference1<std::forward_iterator_tag>();
    test_set_symmetric_difference1<std::input_iterator_tag>();
}

///////////////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference2(ExPolicy const& policy, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::test_iterator<base_iterator, IteratorTag> iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    auto comp = [](std::size_t l, std::size_t r) { return l > r; };

    std::sort(boost::begin(c1), boost::end(c1), comp);
    std::sort(boost::begin(c2), boost::end(c2), comp);

    std::vector<std::size_t> c3(2*c1.size()), c4(2*c1.size());

    hpx::parallel::set_symmetric_difference(policy,
        iterator(boost::begin(c1)), iterator(boost::end(c1)),
        boost::begin(c2), boost::end(c2), boost::begin(c3), comp);

    std::set_symmetric_difference(boost::begin(c1), boost::end(c1),
        boost::begin(c2), boost::end(c2), boost::begin(c4), comp);

    // verify values
    HPX_TEST(std::equal(boost::begin(c3), boost::end(c3), boost::begin(c4)));
}

template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference2_async(ExPolicy const& p, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::test_iterator<base_iterator, IteratorTag> iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    auto comp = [](std::size_t l, std::size_t r) { return l > r; };

    std::sort(boost::begin(c1), boost::end(c1), comp);
    std::sort(boost::begin(c2), boost::end(c2), comp);

    std::vector<std::size_t> c3(2*c1.size()), c4(2*c1.size());

    hpx::future<void> result =
        hpx::parallel::set_symmetric_difference(p,
            iterator(boost::begin(c1)), iterator(boost::end(c1)),
            boost::begin(c2), boost::end(c2), boost::begin(c3), comp);
    result.wait();

    std::set_symmetric_difference(boost::begin(c1), boost::end(c1),
        boost::begin(c2), boost::end(c2), boost::begin(c4), comp);

    // verify values
    HPX_TEST(std::equal(boost::begin(c3), boost::end(c3), boost::begin(c4)));
}

template <typename IteratorTag>
void test_set_symmetric_difference2()
{
    using namespace hpx::parallel;

    test_set_symmetric_difference2(seq, IteratorTag());
    test_set_symmetric_difference2(par, IteratorTag());
    test_set_symmetric_difference2(par_vec, IteratorTag());

    test_set_symmetric_difference2_async(seq(task), IteratorTag());
    test_set_symmetric_difference2_async(par(task), IteratorTag());

    test_set_symmetric_difference2(execution_policy(seq), IteratorTag());
    test_set_symmetric_difference2(execution_policy(par), IteratorTag());
    test_set_symmetric_difference2(execution_policy(par_vec), IteratorTag());

    test_set_symmetric_difference2(execution_policy(seq(task)), IteratorTag());
    test_set_symmetric_difference2(execution_policy(par(task)), IteratorTag());
}

void set_symmetric_difference_test2()
{
    test_set_symmetric_difference2<std::random_access_iterator_tag>();
    test_set_symmetric_difference2<std::forward_iterator_tag>();
    test_set_symmetric_difference2<std::input_iterator_tag>();
}

///////////////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference_exception(ExPolicy const& policy, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::decorated_iterator<base_iterator, IteratorTag>
        decorated_iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size());

    bool caught_exception = false;
    try {
        hpx::parallel::set_symmetric_difference(policy,
            decorated_iterator(
                boost::begin(c1),
                [](){ throw std::runtime_error("test"); }),
            decorated_iterator(boost::end(c1)),
            boost::begin(c2), boost::end(c2),
            boost::begin(c3));

        HPX_TEST(false);
    }
    catch(hpx::exception_list const& e) {
        caught_exception = true;
        test::test_num_exceptions<ExPolicy, IteratorTag>::call(policy, e);
    }
    catch(...) {
        HPX_TEST(false);
    }

    HPX_TEST(caught_exception);
}

template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference_exception_async(ExPolicy const& p, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::decorated_iterator<base_iterator, IteratorTag>
        decorated_iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size());

    bool caught_exception = false;
    bool returned_from_algorithm = false;
    try {
        hpx::future<void> f =
            hpx::parallel::set_symmetric_difference(p,
                decorated_iterator(
                    boost::begin(c1),
                    [](){ throw std::runtime_error("test"); }),
                decorated_iterator(boost::end(c1)),
                boost::begin(c2), boost::end(c2),
                boost::begin(c3));

        returned_from_algorithm = true;
        f.get();

        HPX_TEST(false);
    }
    catch(hpx::exception_list const& e) {
        caught_exception = true;
        test::test_num_exceptions<ExPolicy, IteratorTag>::call(p, e);
    }
    catch(...) {
        HPX_TEST(false);
    }

    HPX_TEST(caught_exception);
    HPX_TEST(returned_from_algorithm);
}

template <typename IteratorTag>
void test_set_symmetric_difference_exception()
{
    using namespace hpx::parallel;

    // If the execution policy object is of type vector_execution_policy,
    // std::terminate shall be called. therefore we do not test exceptions
    // with a vector execution policy
    test_set_symmetric_difference_exception(seq, IteratorTag());
    test_set_symmetric_difference_exception(par, IteratorTag());

    test_set_symmetric_difference_exception_async(seq(task), IteratorTag());
    test_set_symmetric_difference_exception_async(par(task), IteratorTag());

    test_set_symmetric_difference_exception(execution_policy(seq), IteratorTag());
    test_set_symmetric_difference_exception(execution_policy(par), IteratorTag());

    test_set_symmetric_difference_exception(execution_policy(seq(task)), IteratorTag());
    test_set_symmetric_difference_exception(execution_policy(par(task)), IteratorTag());
}

void set_symmetric_difference_exception_test()
{
    test_set_symmetric_difference_exception<std::random_access_iterator_tag>();
    test_set_symmetric_difference_exception<std::forward_iterator_tag>();
    test_set_symmetric_difference_exception<std::input_iterator_tag>();
}

///////////////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference_bad_alloc(ExPolicy const& policy, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::decorated_iterator<base_iterator, IteratorTag>
        decorated_iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size());

    bool caught_bad_alloc = false;
    try {
        hpx::parallel::set_symmetric_difference(policy,
            decorated_iterator(
                boost::begin(c1),
                [](){ throw std::bad_alloc(); }),
            decorated_iterator(boost::end(c1)),
            boost::begin(c2), boost::end(c2),
            boost::begin(c3));

        HPX_TEST(false);
    }
    catch(std::bad_alloc const&) {
        caught_bad_alloc = true;
    }
    catch(...) {
        HPX_TEST(false);
    }

    HPX_TEST(caught_bad_alloc);
}

template <typename ExPolicy, typename IteratorTag>
void test_set_symmetric_difference_bad_alloc_async(ExPolicy const& p, IteratorTag)
{
    BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

    typedef std::vector<std::size_t>::iterator base_iterator;
    typedef test::decorated_iterator<base_iterator, IteratorTag>
        decorated_iterator;

    std::vector<std::size_t> c1 = test::random_fill(10007);
    std::vector<std::size_t> c2 = test::random_fill(c1.size());

    std::sort(boost::begin(c1), boost::end(c1));
    std::sort(boost::begin(c2), boost::end(c2));

    std::vector<std::size_t> c3(2*c1.size());

    bool caught_bad_alloc = false;
    bool returned_from_algorithm = false;
    try {
        hpx::future<void> f =
            hpx::parallel::set_symmetric_difference(p,
                decorated_iterator(
                    boost::begin(c1),
                    [](){ throw std::bad_alloc(); }),
                decorated_iterator(boost::end(c1)),
                boost::begin(c2), boost::end(c2),
                boost::begin(c3));

        returned_from_algorithm = true;
        f.get();

        HPX_TEST(false);
    }
    catch(std::bad_alloc const&) {
        caught_bad_alloc = true;
    }
    catch(...) {
        HPX_TEST(false);
    }

    HPX_TEST(caught_bad_alloc);
    HPX_TEST(returned_from_algorithm);
}

template <typename IteratorTag>
void test_set_symmetric_difference_bad_alloc()
{
    using namespace hpx::parallel;

    // If the execution policy object is of type vector_execution_policy,
    // std::terminate shall be called. therefore we do not test exceptions
    // with a vector execution policy
    test_set_symmetric_difference_bad_alloc(seq, IteratorTag());
    test_set_symmetric_difference_bad_alloc(par, IteratorTag());

    test_set_symmetric_difference_bad_alloc_async(seq(task), IteratorTag());
    test_set_symmetric_difference_bad_alloc_async(par(task), IteratorTag());

    test_set_symmetric_difference_bad_alloc(execution_policy(seq), IteratorTag());
    test_set_symmetric_difference_bad_alloc(execution_policy(par), IteratorTag());

    test_set_symmetric_difference_bad_alloc(execution_policy(seq(task)), IteratorTag());
    test_set_symmetric_difference_bad_alloc(execution_policy(par(task)), IteratorTag());
}

void set_symmetric_difference_bad_alloc_test()
{
    test_set_symmetric_difference_bad_alloc<std::random_access_iterator_tag>();
    test_set_symmetric_difference_bad_alloc<std::forward_iterator_tag>();
    test_set_symmetric_difference_bad_alloc<std::input_iterator_tag>();
}

///////////////////////////////////////////////////////////////////////////////
int hpx_main(boost::program_options::variables_map& vm)
{
    unsigned int seed = (unsigned int)std::time(0);
    if (vm.count("seed"))
        seed = vm["seed"].as<unsigned int>();

    std::cout << "using seed: " << seed << std::endl;
    std::srand(seed);

    set_symmetric_difference_test1();
    set_symmetric_difference_test2();
    set_symmetric_difference_exception_test();
    set_symmetric_difference_bad_alloc_test();
    return hpx::finalize();
}

int main(int argc, char* argv[])
{
    // add command line option which controls the random number generator seed
    using namespace boost::program_options;
    options_description desc_commandline(
        "Usage: " HPX_APPLICATION_STRING " [options]");

    desc_commandline.add_options()
        ("seed,s", value<unsigned int>(),
        "the random number generator seed to use for this run")
        ;

    // By default this test should run on all available cores
    std::vector<std::string> cfg;
    cfg.push_back("hpx.os_threads=" +
        boost::lexical_cast<std::string>(hpx::threads::hardware_concurrency()));

    // Initialize and run HPX
    HPX_TEST_EQ_MSG(hpx::init(desc_commandline, argc, argv, cfg), 0,
        "HPX main exited with non-zero status");

    return hpx::util::report_errors();
}


#include "series.h"
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <stdexcept>

using namespace std;
namespace tt = boost::test_tools;

BOOST_AUTO_TEST_CASE(short_digits)
{
    const vector<int> expected{0, 1, 2, 3, 4, 5};

    const vector<int> actual{series::digits("012345")};

    BOOST_TEST(expected == actual, tt::per_element());
}

BOOST_AUTO_TEST_CASE(long_digits)
{
    const vector<int> expected{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    const vector<int> actual{series::digits("0123456789")};

    BOOST_TEST(expected == actual, tt::per_element());
}

BOOST_AUTO_TEST_CASE(keeps_the_digit_order_if_reversed)
{
    const vector<int> expected{9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

    const vector<int> actual{series::digits("9876543210")};

    BOOST_TEST(expected == actual, tt::per_element());
}

BOOST_AUTO_TEST_CASE(keeps_arbitrary_digit_order)
{
    const vector<int> expected{9, 3, 6, 9, 2, 3, 4, 6, 8};

    const vector<int> actual{series::digits("936923468")};

    BOOST_TEST(expected == actual, tt::per_element());
}

BOOST_AUTO_TEST_CASE(can_slice_by_1)
{
    const vector<vector<int>> expected{{0}, {1}, {2}, {3}, {4}};

    const vector<vector<int>> actual{series::slice("01234", 1)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(can_slice_by_2)
{
    const vector<vector<int>> expected{{9, 8}, {8, 2}, {2, 7}, {7, 3}, {3, 4}, {4, 6}, {6, 3}};

    const vector<vector<int>> actual{series::slice("98273463", 2)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(can_slice_by_3)
{
    const vector<vector<int>> expected{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};

    const vector<vector<int>> actual{series::slice("01234", 3)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(can_slice_by_3_with_duplicate_digits)
{
    const vector<vector<int>> expected{{3, 1, 0}, {1, 0, 0}, {0, 0, 1}};

    const vector<vector<int>> actual{series::slice("31001", 3)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(can_slice_by_4)
{
    const vector<vector<int>> expected{{3, 1, 0}, {1, 0, 0}, {0, 0, 1}};

    const vector<vector<int>> actual{series::slice("31001", 3)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(can_slice_by_5)
{
    const vector<vector<int>> expected{{8, 1, 2, 2, 8}};

    const vector<vector<int>> actual{series::slice("81228", 5)};

    BOOST_TEST(expected == actual);
}

BOOST_AUTO_TEST_CASE(domain_error_if_not_enough_digits_to_slice)
{
    BOOST_REQUIRE_THROW(series::slice("01032987583", 12), domain_error);
}
#if defined(EXERCISM_RUN_ALL_TESTS)
#endif


// featureNormalize.hpp
#ifndef COURSERA_FEATURENORMALIZE_HPP
#define COURSERA_FEATURENORMALIZE_HPP

#include <memory>
#include <armadillo>

void featureNormalize(std::shared_ptr<arma::fmat> &X_norm, std::shared_ptr<arma::frowvec> &mu,
                      std::shared_ptr<arma::frowvec> &sigma, const arma::fmat &X);

#endif // COURSERA_FEATURENORMALIZE_HPP


/* ----------------------------------------------------------------------------

 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 * Atlanta, Georgia 30332-0415
 * All Rights Reserved
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)

 * See LICENSE for the license information

 * -------------------------------------------------------------------------- */

/**
 *  @file   testCameraSet.cpp
 *  @brief  Unit tests for testCameraSet Class
 *  @author Frank Dellaert
 *  @date   Feb 19, 2015
 */

#include <gtsam/geometry/CameraSet.h>
#include <gtsam/geometry/Pose3.h>
#include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/bind.hpp>

using namespace std;
using namespace gtsam;

/* ************************************************************************* */
// Cal3Bundler test
#include <gtsam/geometry/PinholeCamera.h>
#include <gtsam/geometry/Cal3Bundler.h>
TEST(CameraSet, Pinhole) {
  typedef PinholeCamera<Cal3Bundler> Camera;
  typedef CameraSet<Camera> Set;
  typedef Point2Vector ZZ;
  Set set;
  Camera camera;
  set.push_back(camera);
  set.push_back(camera);
  Point3 p(0, 0, 1);
  EXPECT(assert_equal(set, set));
  Set set2 = set;
  set2.push_back(camera);
  EXPECT(!set.equals(set2));

  // Check measurements
  Point2 expected(0,0);
  ZZ z = set.project2(p);
  EXPECT(assert_equal(expected, z[0]));
  EXPECT(assert_equal(expected, z[1]));

  // Calculate expected derivatives using Pinhole
  Matrix actualE;
  Matrix29 F1;
  {
    Matrix23 E1;
    camera.project2(p, F1, E1);
    actualE.resize(4,3);
    actualE << E1, E1;
  }

  // Check computed derivatives
  Set::FBlocks Fs;
  Matrix E;
  set.project2(p, Fs, E);
  LONGS_EQUAL(2, Fs.size());
  EXPECT(assert_equal(F1, Fs[0]));
  EXPECT(assert_equal(F1, Fs[1]));
  EXPECT(assert_equal(actualE, E));

  // Check errors
  ZZ measured;
  measured.push_back(Point2(1, 2));
  measured.push_back(Point2(3, 4));
  Vector4 expectedV;

  // reprojectionError
  expectedV << -1, -2, -3, -4;
  Vector actualV = set.reprojectionError(p, measured);
  EXPECT(assert_equal(expectedV, actualV));

  // Check Schur complement
  Matrix F(4, 18);
  F << F1, Matrix29::Zero(), Matrix29::Zero(), F1;
  Matrix Ft = F.transpose();
  Matrix34 Et = E.transpose();
  Matrix3 P = Et * E;
  Matrix schur(19, 19);
  Vector4 b = actualV;
  Vector v = Ft * (b - E * P * Et * b);
  schur << Ft * F - Ft * E * P * Et * F, v, v.transpose(), 30;
  SymmetricBlockMatrix actualReduced = Set::SchurComplement<3>(Fs, E, P, b);
  EXPECT(assert_equal(schur, actualReduced.selfadjointView()));

  // Check Schur complement update, same order, should just double
  KeyVector allKeys {1, 2}, keys {1, 2};
  Set::UpdateSchurComplement<3>(Fs, E, P, b, allKeys, keys, actualReduced);
  EXPECT(assert_equal((Matrix )(2.0 * schur), actualReduced.selfadjointView()));

  // Check Schur complement update, keys reversed
  KeyVector keys2 {2, 1};
  Set::UpdateSchurComplement<3>(Fs, E, P, b, allKeys, keys2, actualReduced);
  Vector4 reverse_b;
  reverse_b << b.tail<2>(), b.head<2>();
  Vector reverse_v = Ft * (reverse_b - E * P * Et * reverse_b);
  Matrix A(19, 19);
  A << Ft * F - Ft * E * P * Et * F, reverse_v, reverse_v.transpose(), 30;
  EXPECT(assert_equal((Matrix )(2.0 * schur + A), actualReduced.selfadjointView()));

  // reprojectionErrorAtInfinity
  Unit3 pointAtInfinity(0, 0, 1000);
  EXPECT(
      assert_equal(pointAtInfinity,
          camera.backprojectPointAtInfinity(Point2(0,0))));
  actualV = set.reprojectionError(pointAtInfinity, measured, Fs, E);
  EXPECT(assert_equal(expectedV, actualV));
  LONGS_EQUAL(2, Fs.size());
  {
    Matrix22 E1;
    camera.project2(pointAtInfinity, F1, E1);
    actualE.resize(4,2);
    actualE << E1, E1;
  }
  EXPECT(assert_equal(F1, Fs[0]));
  EXPECT(assert_equal(F1, Fs[1]));
  EXPECT(assert_equal(actualE, E));
}

/* ************************************************************************* */
#include <gtsam/geometry/StereoCamera.h>
TEST(CameraSet, Stereo) {
  CameraSet<StereoCamera> set;
  typedef StereoCamera::MeasurementVector ZZ;
  StereoCamera camera;
  set.push_back(camera);
  set.push_back(camera);
  Point3 p(0, 0, 1);
  EXPECT_LONGS_EQUAL(6, traits<StereoCamera>::dimension);

  // Check measurements
  StereoPoint2 expected(0, -1, 0);
  ZZ z = set.project2(p);
  EXPECT(assert_equal(expected, z[0]));
  EXPECT(assert_equal(expected, z[1]));

  // Calculate expected derivatives using Pinhole
  Matrix63 actualE;
  Matrix F1;
  {
    Matrix33 E1;
    camera.project2(p, F1, E1);
    actualE << E1, E1;
  }

  // Check computed derivatives
  CameraSet<StereoCamera>::FBlocks Fs;
  Matrix E;
  set.project2(p, Fs, E);
  LONGS_EQUAL(2, Fs.size());
  EXPECT(assert_equal(F1, Fs[0]));
  EXPECT(assert_equal(F1, Fs[1]));
  EXPECT(assert_equal(actualE, E));
}

/* ************************************************************************* */
int main() {
  TestResult tr;
  return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */