/*
Copyright (C) 2013 Tom Bachmann
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#include
#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 make3;
typedef make_tuple make2;
typedef make_tuple make1;
tassert((equal_types<
make3::type,
tuple > >
>::val));
tassert((equal_types<
make2::type,
tuple >
>::val));
tassert((equal_types >::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 makeref;
tassert((equal_types::val));
int a = 4;
makeref::type reftup = makeref::make(a, a);
tassert(reftup.head == 4);
a = 5;
tassert(reftup.second() == 5);
}
template
struct type_n
{
int payload;
type_n(int p) : payload(p) {};
};
template
struct type_n
{
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 make3;
typedef make_tuple make3p;
typedef make_tuple make2A;
typedef make_tuple make2B;
typedef back_tuple backvoid;
typedef back_tuple backD;
typedef back_tuple backA;
typedef back_tuple backB;
tassert((equal_types::val));
tassert((equal_types::val));
tassert((equal_types::val));
tassert((equal_types::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::type, empty_tuple>::val));
typedef tuple tup1_t;
tassert((equal_types::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 make1st;
typedef make_tuple make2nd;
typedef concat_tuple concater;
tassert((equal_types<
concater::type,
tuple > >
>::val));
concater::type concated = concater::type(0,
tuple >(1,
tuple(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::type,
empty_tuple
>::val));
typedef tuple tup1_t;
tassert((equal_types<
concat_tuple::type,
tup1_t
>::val));
tassert((equal_types<
concat_tuple::type,
tup1_t
>::val));
}
namespace flint{
namespace detail
{
template
struct fillit
{
static void doit(T& t, int start)
{
t.head.payload = start;
detail::fillit::doit(t.tail, ++start);
}
};
template<>
struct fillit
{
static void doit(empty_tuple e, int start)
{
}
};
template
struct values
{
static void doit(const T& t, std::set& values)
{
values.insert(t.head.payload);
detail::values::doit(t.tail, values);
}
};
template<>
struct values
{
static void doit(empty_tuple e, std::set& values)
{
}
};
}
}
template
void fillit(T& t, int start = 1)
{
detail::fillit::doit(t, start);
}
template
std::set values(const T& t)
{
std::set ret;
detail::values::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 and
// 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 m1; \
typedef make_tuple m2; \
typedef merge_tuple merge1; \
typedef merge_tuple 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 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 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 emptymerge;
tassert((equal_types::val));
typedef merge_tuple::type, empty_tuple> anothermerge;
tassert(anothermerge::type::len == 2);
}
void
test_traits()
{
tassert((is_homogeneous_tuple::type, int>::val
== true));
tassert((is_homogeneous_tuple::type, int>::val
== false));
tassert(is_tuple::val == true);
tassert(is_tuple::type>::val == true);
tassert((is_tuple::type>::val == true));
tassert(is_tuple::val == false);
}
struct filler
{
template
T create() const
{
if(mp::equal_types::val)
return 1;
return 0;
}
};
void
test_htuples()
{
tassert((equal_types::type,
make_homogeneous_tuple::type>::val));
typedef make_tuple maker;
maker::type tpl = maker::make(1, 2, 3);
tassert(htuples::extract<1>(tpl) == make_tuple::make(1));
tassert((htuples::extract<2>(tpl) == make_tuple::make(1, 2)));
tassert((htuples::extract<3>(tpl) == make_tuple::make(1, 2, 3)));
typedef make_tuple 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 maker3;
tassert((maker3::make(0, 1, 0) == htuples::fill(filler())));
}
void
test_get()
{
typedef make_tuple::type tuple_t;
int a, b;
tuple_t t(17, make_tuple::type(a,
make_tuple::type(b, empty_tuple())));
tassert((equal_types::type>::val));
tassert((equal_types::type>::val));
tassert((equal_types::type>::val));
tassert((tuple_get::get(t) == 17));
tuple_get::get(t) = 42;
b = 3;
tassert((tuple_get::get(t) == 3));
tassert(a == 42);
const tuple_t ct(t);
tuple_get::get(ct) = 17;
tassert((tuple_get::get(ct) == 17));
}
void
test_set()
{
make_tuple::type tup;
tup.set(make_tuple::make(1, 2, 3));
tassert((tup == make_tuple::make(1, 2, 3)));
}
void
test_equals_elementwise()
{
tassert((make_tuple::make(1, 2, 3).equals_elementwise(
make_tuple::make(1, 2, 3))));
tassert((!make_tuple::make(0, 2, 3).equals_elementwise(
make_tuple::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;
}