pqc/external/flint-2.4.3/flintxx/test/t-tuple.cpp
2014-05-24 23:16:06 +02:00

418 lines
12 KiB
C++

/*=============================================================================
This file is part of FLINT.
FLINT 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.
FLINT 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 FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2013 Tom Bachmann
******************************************************************************/
#include <set>
#include "flintxx/test/helpers.h"
#include "flintxx/tuple.h"
#include "flintxx/mp.h"
using namespace flint;
using namespace mp;
using namespace traits;
void
test_make()
{
typedef make_tuple<int, char, int> make3;
typedef make_tuple<int, char> make2;
typedef make_tuple<int> make1;
tassert((equal_types<
make3::type,
tuple<int, tuple<char, tuple<int, empty_tuple> > >
>::val));
tassert((equal_types<
make2::type,
tuple<int, tuple<char, empty_tuple> >
>::val));
tassert((equal_types<make1::type, tuple<int, empty_tuple> >::val));
tassert(make3::type::len == 3);
tassert(make2::type::len == 2);
tassert(make1::type::len == 1);
make3::type tup = make3::make(1, 'b', 3);
tassert(tup.head == 1);
tassert(tup.tail.head == 'b');
tassert(tup.tail.tail.head == 3);
tup.first() = 2;
tassert(tup.head == 2);
tassert(tup.second() == 'b');
make2::type pair = make2::make(1, 'b');
tassert(pair.first() == 1);
tassert(pair.second() == 'b');
make1::type singleton = make1::make(1);
tassert(singleton.first() == 1);
typedef make_tuple<const int&, const int&> makeref;
tassert((equal_types<makeref::type::head_t, const int&>::val));
int a = 4;
makeref::type reftup = makeref::make(a, a);
tassert(reftup.head == 4);
a = 5;
tassert(reftup.second() == 5);
}
template<int i, bool default_ctor = false>
struct type_n
{
int payload;
type_n(int p) : payload(p) {};
};
template<int i>
struct type_n<i, true>
{
int payload;
type_n(int p) : payload(p) {};
type_n() {};
};
void
test_back()
{
typedef type_n<0> A;
typedef type_n<1> B;
typedef type_n<2> C;
typedef type_n<3> D;
typedef make_tuple<A, B, C> make3;
typedef make_tuple<A*, B*, C*> make3p;
typedef make_tuple<B, C> make2A;
typedef make_tuple<A, C> make2B;
typedef back_tuple<make3p::type, void> backvoid;
typedef back_tuple<make3p::type, D> backD;
typedef back_tuple<make3p::type, A> backA;
typedef back_tuple<make3p::type, B> backB;
tassert((equal_types<backvoid::type, make3::type>::val));
tassert((equal_types<backD::type, make3::type>::val));
tassert((equal_types<backA::type, make2A::type>::val));
tassert((equal_types<backB::type, make2B::type>::val));
make3::type backing = make3::make(1, 2, 3);
make3p::type pointers;
backvoid::init(pointers, backing, 0);
tassert(pointers.first()->payload == 1);
backing.second() = 4;
tassert(pointers.second()->payload == 4);
A ret = 4;
make2A::type backing2 = make2A::make(1, 2);
backA::init(pointers, backing2, &ret);
tassert(pointers.first()->payload == 4);
tassert(pointers.second()->payload == 1);
ret.payload = 5;
backing2.head.payload = 6;
tassert(pointers.first()->payload == 5);
tassert(pointers.second()->payload == 6);
// Test some corner cases.
tassert((equal_types<back_tuple<empty_tuple>::type, empty_tuple>::val));
typedef tuple<int*, empty_tuple> tup1_t;
tassert((equal_types<back_tuple<tup1_t, int>::type, empty_tuple>::val));
}
void
test_concat()
{
typedef type_n<0> A;
typedef type_n<1> B;
typedef type_n<2> C;
typedef type_n<3> D;
typedef type_n<4> E;
typedef make_tuple<A, B, C> make1st;
typedef make_tuple<D, E> make2nd;
typedef concat_tuple<make1st::type, make2nd::type> concater;
tassert((equal_types<
concater::type,
tuple<A, tuple<B, tuple<C, make2nd::type> > >
>::val));
concater::type concated = concater::type(0,
tuple<B, tuple<C, make2nd::type> >(1,
tuple<C, make2nd::type>(2, make2nd::make(3, 4))));
make2nd::type second = concater::get_second(concated);
tassert(second.first().payload == 3);
tassert(second.second().payload == 4);
make1st::type first = concater::get_first(concated);
tassert(first.first().payload == 0);
tassert(first.second().payload == 1);
tassert(first.tail.second().payload == 2);
first.first().payload = 17;
second.first().payload = 18;
concated = concater::doit(first, second);
tassert(concated.first().payload == 17);
tassert(concated.tail.tail.tail.head.payload == 18);
// Test a few corner cases.
tassert((equal_types<
concat_tuple<empty_tuple, empty_tuple>::type,
empty_tuple
>::val));
typedef tuple<int, empty_tuple> tup1_t;
tassert((equal_types<
concat_tuple<tup1_t, empty_tuple>::type,
tup1_t
>::val));
tassert((equal_types<
concat_tuple<empty_tuple, tup1_t>::type,
tup1_t
>::val));
}
namespace flint{
namespace detail
{
template<class T>
struct fillit
{
static void doit(T& t, int start)
{
t.head.payload = start;
detail::fillit<typename T::tail_t>::doit(t.tail, ++start);
}
};
template<>
struct fillit<empty_tuple>
{
static void doit(empty_tuple e, int start)
{
}
};
template<class T>
struct values
{
static void doit(const T& t, std::set<int>& values)
{
values.insert(t.head.payload);
detail::values<typename T::tail_t>::doit(t.tail, values);
}
};
template<>
struct values<empty_tuple>
{
static void doit(empty_tuple e, std::set<int>& values)
{
}
};
}
}
template<class T>
void fillit(T& t, int start = 1)
{
detail::fillit<T>::doit(t, start);
}
template<class T>
std::set<int> values(const T& t)
{
std::set<int> ret;
detail::values<T>::doit(t, ret);
return ret;
}
void
test_merge()
{
typedef type_n<0, true> A;
typedef type_n<1, true> B;
typedef type_n<2, true> C;
typedef type_n<3, true> D;
typedef type_n<4, true> E;
// Test that merging tuples <T1, T2, T3> and <U1, U2>
// yields something of length n, and that the constitutents can be
// recovered. Also do other order.
#define TEST32n(T1, T2, T3, U1, U2, n) \
{ \
typedef make_tuple<T1, T2, T3> m1; \
typedef make_tuple<U1, U2> m2; \
typedef merge_tuple<m1::type, m2::type> merge1; \
typedef merge_tuple<m2::type, m1::type> merge2; \
tassert(merge1::type::len == n); \
tassert(merge2::type::len == n); \
merge1::type merged1; \
{ \
fillit(merged1); \
m1::type n1 = merge1::get_first(merged1); \
m2::type n2 = merge1::get_second(merged1); \
std::set<int> vals1 = values(n1), vals2 = values(n2); \
vals1.insert(vals2.begin(), vals2.end()); \
tassert(vals1.size() == n); \
} \
merge2::type merged2; \
{ \
fillit(merged2); \
m2::type n2 = merge2::get_first(merged2); \
m1::type n1 = merge2::get_second(merged2); \
std::set<int> vals1 = values(n1), vals2 = values(n2); \
vals1.insert(vals2.begin(), vals2.end()); \
tassert(vals1.size() == n); \
} \
}
TEST32n(A, B, C, A, B, 3);
TEST32n(A, B, C, B, A, 3);
TEST32n(A, B, C, A, C, 3);
TEST32n(A, B, C, C, A, 3);
TEST32n(A, B, C, C, B, 3);
TEST32n(A, B, C, B, C, 3);
TEST32n(A, A, A, A, A, 3);
TEST32n(A, B, C, A, D, 4);
TEST32n(A, B, C, B, D, 4);
TEST32n(A, B, C, C, D, 4);
TEST32n(A, B, C, D, A, 4);
TEST32n(A, B, C, D, B, 4);
TEST32n(A, B, C, D, C, 4);
TEST32n(A, A, A, A, B, 4);
TEST32n(A, B, C, D, E, 5);
TEST32n(A, A, A, B, B, 5);
typedef merge_tuple<empty_tuple, empty_tuple> emptymerge;
tassert((equal_types<emptymerge::type, empty_tuple>::val));
typedef merge_tuple<make_tuple<A, A>::type, empty_tuple> anothermerge;
tassert(anothermerge::type::len == 2);
}
void
test_traits()
{
tassert((is_homogeneous_tuple<make_tuple<int, int, int>::type, int>::val
== true));
tassert((is_homogeneous_tuple<make_tuple<int, char, int>::type, int>::val
== false));
tassert(is_tuple<empty_tuple>::val == true);
tassert(is_tuple<make_tuple<int>::type>::val == true);
tassert((is_tuple<make_tuple<int, slong>::type>::val == true));
tassert(is_tuple<int>::val == false);
}
struct filler
{
template<class T>
T create() const
{
if(mp::equal_types<T, slong>::val)
return 1;
return 0;
}
};
void
test_htuples()
{
tassert((equal_types<make_tuple<int, int, int>::type,
make_homogeneous_tuple<int, 3>::type>::val));
typedef make_tuple<int, int, int> maker;
maker::type tpl = maker::make(1, 2, 3);
tassert(htuples::extract<1>(tpl) == make_tuple<int>::make(1));
tassert((htuples::extract<2>(tpl) == make_tuple<int, int>::make(1, 2)));
tassert((htuples::extract<3>(tpl) == make_tuple<int, int, int>::make(1, 2, 3)));
typedef make_tuple<int, int> make2;
tassert(htuples::removeres(tpl, 1) == make2::make(2, 3));
tassert(htuples::removeres(tpl, 2) == make2::make(1, 3));
tassert(htuples::removeres(tpl, 3) == make2::make(1, 2));
tassert(htuples::removeres(tpl, 4) == make2::make(1, 2));
typedef make_tuple<int, slong, int> maker3;
tassert((maker3::make(0, 1, 0) == htuples::fill<maker3::type>(filler())));
}
void
test_get()
{
typedef make_tuple<int, int&, const int&>::type tuple_t;
int a, b;
tuple_t t(17, make_tuple<int&, const int&>::type(a,
make_tuple<const int&>::type(b, empty_tuple())));
tassert((equal_types<int, tuple_get<tuple_t, 0>::type>::val));
tassert((equal_types<int&, tuple_get<tuple_t, 1>::type>::val));
tassert((equal_types<const int&, tuple_get<tuple_t, 2>::type>::val));
tassert((tuple_get<tuple_t, 0>::get(t) == 17));
tuple_get<tuple_t, 1>::get(t) = 42;
b = 3;
tassert((tuple_get<tuple_t, 2>::get(t) == 3));
tassert(a == 42);
const tuple_t ct(t);
tuple_get<tuple_t, 1>::get(ct) = 17;
tassert((tuple_get<tuple_t, 1>::get(ct) == 17));
}
void
test_set()
{
make_tuple<int, int, int>::type tup;
tup.set(make_tuple<int, char, short>::make(1, 2, 3));
tassert((tup == make_tuple<int, int, int>::make(1, 2, 3)));
}
void
test_equals_elementwise()
{
tassert((make_tuple<int, int, int>::make(1, 2, 3).equals_elementwise(
make_tuple<int, char, slong>::make(1, 2, 3))));
tassert((!make_tuple<int, int, int>::make(0, 2, 3).equals_elementwise(
make_tuple<int, char, slong>::make(1, 2, 3))));
}
int
main()
{
std::cout << "tuple....";
test_make();
test_back();
test_concat();
test_merge();
test_traits();
test_htuples();
test_get();
test_set();
test_equals_elementwise();
std::cout << "PASS" << std::endl;
return 0;
}