hana/test/numeric/main.hpp
2017-01-07 14:14:18 -08:00

512 lines
15 KiB
C++

// Copyright Louis Dionne 2013-2017
// 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/and.hpp>
#include <boost/hana/assert.hpp>
#include <boost/hana/comparing.hpp>
#include <boost/hana/div.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/eval_if.hpp>
#include <boost/hana/greater.hpp>
#include <boost/hana/greater_equal.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/less.hpp>
#include <boost/hana/less_equal.hpp>
#include <boost/hana/max.hpp>
#include <boost/hana/min.hpp>
#include <boost/hana/minus.hpp>
#include <boost/hana/mod.hpp>
#include <boost/hana/mult.hpp>
#include <boost/hana/negate.hpp>
#include <boost/hana/not.hpp>
#include <boost/hana/not_equal.hpp>
#include <boost/hana/one.hpp>
#include <boost/hana/or.hpp>
#include <boost/hana/ordering.hpp>
#include <boost/hana/plus.hpp>
#include <boost/hana/power.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/while.hpp>
#include <boost/hana/zero.hpp>
#include <laws/base.hpp>
#include <laws/comparable.hpp>
#include <laws/euclidean_ring.hpp>
#include <laws/group.hpp>
#include <laws/logical.hpp>
#include <laws/monoid.hpp>
#include <laws/orderable.hpp>
#include <support/cnumeric.hpp>
#include <support/numeric.hpp>
#include <cstdlib>
#include <vector>
namespace hana = boost::hana;
struct invalid {
template <typename T>
operator T const() { std::abort(); }
};
int main() {
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
{
hana::test::_injection<0> f{};
auto x = numeric(1);
auto y = numeric(2);
// equal
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(x, x));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(x, y)));
}
// not_equal
{
BOOST_HANA_CONSTEXPR_CHECK(hana::not_equal(x, y));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::not_equal(x, x)));
}
// comparing
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::comparing(f)(x, x),
hana::equal(f(x), f(x))
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::comparing(f)(x, y),
hana::equal(f(x), f(y))
));
}
}
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
{
auto ord = numeric;
// _injection is also monotonic
hana::test::_injection<0> f{};
// less
{
BOOST_HANA_CONSTEXPR_CHECK(hana::less(ord(0), ord(1)));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less(ord(0), ord(0))));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less(ord(1), ord(0))));
}
// less_equal
{
BOOST_HANA_CONSTEXPR_CHECK(hana::less_equal(ord(0), ord(1)));
BOOST_HANA_CONSTEXPR_CHECK(hana::less_equal(ord(0), ord(0)));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less_equal(ord(1), ord(0))));
}
// greater_equal
{
BOOST_HANA_CONSTEXPR_CHECK(hana::greater_equal(ord(1), ord(0)));
BOOST_HANA_CONSTEXPR_CHECK(hana::greater_equal(ord(0), ord(0)));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater_equal(ord(0), ord(1))));
}
// greater
{
BOOST_HANA_CONSTEXPR_CHECK(hana::greater(ord(1), ord(0)));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater(ord(0), ord(0))));
BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater(ord(0), ord(1))));
}
// max
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::max(ord(0), ord(0)), ord(0)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::max(ord(1), ord(0)), ord(1)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::max(ord(0), ord(1)), ord(1)
));
}
// min
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::min(ord(0), ord(0)),
ord(0)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::min(ord(1), ord(0)),
ord(0)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::min(ord(0), ord(1)),
ord(0)
));
}
// ordering
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::ordering(f)(ord(1), ord(0)),
hana::less(f(ord(1)), f(ord(0)))
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::ordering(f)(ord(0), ord(1)),
hana::less(f(ord(0)), f(ord(1)))
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::ordering(f)(ord(0), ord(0)),
hana::less(f(ord(0)), f(ord(0)))
));
}
}
//////////////////////////////////////////////////////////////////////////
// Monoid
//////////////////////////////////////////////////////////////////////////
{
constexpr int x = 2, y = 3;
// zero
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::zero<Numeric>(), numeric(0)
));
}
// plus
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::plus(numeric(x), numeric(y)),
numeric(x + y)
));
}
}
//////////////////////////////////////////////////////////////////////////
// Group
//////////////////////////////////////////////////////////////////////////
{
constexpr int x = 2, y = 3;
// minus
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::minus(numeric(x), numeric(y)),
numeric(x - y)
));
}
// negate
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::negate(numeric(x)),
numeric(-x)
));
}
}
//////////////////////////////////////////////////////////////////////////
// Ring
//////////////////////////////////////////////////////////////////////////
{
constexpr int x = 2, y = 3;
// one
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::one<Numeric>(),
numeric(1)
));
}
// mult
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::mult(numeric(x), numeric(y)),
numeric(x * y)
));
}
// power
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::power(numeric(x), hana::zero<CNumeric<int>>()),
hana::one<Numeric>()
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::power(numeric(x), hana::one<CNumeric<int>>()),
numeric(x)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::power(numeric(x), cnumeric<int, 2>),
hana::mult(numeric(x), numeric(x))
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::power(numeric(x), cnumeric<int, 3>),
hana::mult(hana::mult(numeric(x), numeric(x)), numeric(x))
));
}
}
//////////////////////////////////////////////////////////////////////////
// EuclideanRing
//////////////////////////////////////////////////////////////////////////
{
constexpr int x = 6, y = 3, z = 4;
// div
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::div(numeric(x), numeric(y)),
numeric(x / y)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::div(numeric(x), numeric(z)),
numeric(x/ z)
));
}
// mod
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::mod(numeric(x), numeric(y)),
numeric(x % y)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::mod(numeric(x), numeric(z)),
numeric(x % z)
));
}
}
//////////////////////////////////////////////////////////////////////////
// Logical
//////////////////////////////////////////////////////////////////////////
{
auto logical = numeric;
auto comparable = numeric;
// not_
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::not_(logical(true)),
logical(false)
));
}
// and_
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true), logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true), logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(false), invalid{}),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true), logical(true), logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true), logical(true), logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(true), logical(false), invalid{}),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::and_(logical(false), invalid{}, invalid{}),
logical(false)
));
}
// or_
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false), logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false), logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(true), invalid{}),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false), logical(false), logical(false)),
logical(false)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false), logical(false), logical(true)),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(false), logical(true), invalid{}),
logical(true)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::or_(logical(true), invalid{}, invalid{}),
logical(true)
));
}
// if_
{
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::if_(logical(true), comparable(0), comparable(1)),
comparable(0)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::if_(logical(false), comparable(0), comparable(1)),
comparable(1)
));
}
// eval_if
{
auto t = [=](auto) { return comparable(0); };
auto e = [=](auto) { return comparable(1); };
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::eval_if(logical(true), t, e),
comparable(0)
));
BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
hana::eval_if(logical(false), t, e),
comparable(1)
));
}
// while_
{
auto smaller_than = [](auto n) {
return [n](auto v) { return v.size() < n; };
};
auto f = [](auto v) {
v.push_back(v.size());
return v;
};
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(0u), std::vector<int>{}, f),
std::vector<int>{}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(1u), std::vector<int>{}, f),
std::vector<int>{0}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(2u), std::vector<int>{}, f),
std::vector<int>{0, 1}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(3u), std::vector<int>{}, f),
std::vector<int>{0, 1, 2}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(4u), std::vector<int>{}, f),
std::vector<int>{0, 1, 2, 3}
));
// Make sure it can be called with an lvalue state:
std::vector<int> v{};
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(smaller_than(4u), v, f),
std::vector<int>{0, 1, 2, 3}
));
}
// while_
{
auto less_than = [](auto n) {
return [n](auto v) { return v.size() < n; };
};
auto f = [](auto v) {
v.push_back(v.size());
return v;
};
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(0u), std::vector<int>{}, f),
std::vector<int>{}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(1u), std::vector<int>{}, f),
std::vector<int>{0}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(2u), std::vector<int>{}, f),
std::vector<int>{0, 1}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(3u), std::vector<int>{}, f),
std::vector<int>{0, 1, 2}
));
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(4u), std::vector<int>{}, f),
std::vector<int>{0, 1, 2, 3}
));
// Make sure it can be called with an lvalue state:
std::vector<int> v{};
BOOST_HANA_RUNTIME_CHECK(hana::equal(
hana::while_(less_than(4u), v, f),
std::vector<int>{0, 1, 2, 3}
));
}
}
}