thesis version

This commit is contained in:
2021-05-10 18:11:23 +02:00
commit 8d0b353391
152 changed files with 28007 additions and 0 deletions

View File

@ -0,0 +1,77 @@
#include <catch.hpp>
#include "../common.h"
#include <pfor/expression/algorithm.h>
TEST_CASE("Operand Utilities") {
constexpr pfor::expr::Access r = pfor::expr::Access::read, w = pfor::expr::Access::write;
SECTION("WorstAccess") {
TEST_IF(REQUIRE, ==, r, pfor::expr::WorstAccess<r, r, r, r>::value);
TEST_IF(REQUIRE, ==, w, pfor::expr::WorstAccess<r, r, w, r>::value);
TEST_IF(REQUIRE, ==, w, pfor::expr::WorstAccess<r, w, w, r>::value);
TEST_IF(REQUIRE, ==, w, pfor::expr::WorstAccess<w, w, w, r>::value);
TEST_IF(REQUIRE, ==, w, pfor::expr::WorstAccess<w, w, w, w>::value);
}
SECTION("Tags") {
using Iterator = void;
using T1R = pfor::expr::OperandTag<class ID1, r, Iterator>;
using T2R = pfor::expr::OperandTag<class ID2, r, Iterator>;
using T3R = pfor::expr::OperandTag<class ID3, r, Iterator>;
using T1W = pfor::expr::OperandTag<class ID1, w, Iterator>;
using T2W = pfor::expr::OperandTag<class ID2, w, Iterator>;
using T3W = pfor::expr::OperandTag<class ID3, w, Iterator>;
using I0 = pfor::Pack<>;
using I1 = pfor::Pack<T1R, T2R, T3R>;
using I2 = pfor::Pack<T1W, T2W, T3W>;
using I3 = pfor::Pack<T1R, T1W, T2R, T2W, T3R, T3W>;
SECTION("CountWrite") {
using R = pfor::expr::OperandTag<class ID0, r, Iterator>;
using W = pfor::expr::OperandTag<class ID0, w, Iterator>;
TEST_IF(REQUIRE, ==, 0, pfor::expr::CountWrite<pfor::Pack<R, R, R, R>>::value);
TEST_IF(REQUIRE, ==, 1, pfor::expr::CountWrite<pfor::Pack<R, R, W, R>>::value);
TEST_IF(REQUIRE, ==, 2, pfor::expr::CountWrite<pfor::Pack<R, W, W, R>>::value);
TEST_IF(REQUIRE, ==, 3, pfor::expr::CountWrite<pfor::Pack<W, W, W, R>>::value);
TEST_IF(REQUIRE, ==, 4, pfor::expr::CountWrite<pfor::Pack<W, W, W, W>>::value);
}
SECTION("IncludeTags") {
using O0 = pfor::expr::IncludeTags<class ID1, I0>;
using O1 = pfor::expr::IncludeTags<class ID2, I1>;
using O2 = pfor::expr::IncludeTags<class ID3, I2>;
using O3 = pfor::expr::IncludeTags<class ID1, I3>;
using E0 = pfor::Pack<>;
using E1 = pfor::Pack<T2R>;
using E2 = pfor::Pack<T3W>;
using E3 = pfor::Pack<T1R, T1W>;
TEST(REQUIRE, is_same_v<O0, E0>);
TEST(REQUIRE, is_same_v<O1, E1>);
TEST(REQUIRE, is_same_v<O2, E2>);
TEST(REQUIRE, is_same_v<O3, E3>);
}
SECTION("ExcludeTags") {
using O0 = pfor::expr::ExcludeTags<class ID1, I0>;
using O1 = pfor::expr::ExcludeTags<class ID2, I1>;
using O2 = pfor::expr::ExcludeTags<class ID3, I2>;
using O3 = pfor::expr::ExcludeTags<class ID1, I3>;
using E0 = pfor::Pack<>;
using E1 = pfor::Pack<T1R, T3R>;
using E2 = pfor::Pack<T1W, T2W>;
using E3 = pfor::Pack<T2R, T2W, T3R, T3W>;
TEST(REQUIRE, is_same_v<O0, E0>);
TEST(REQUIRE, is_same_v<O1, E1>);
TEST(REQUIRE, is_same_v<O2, E2>);
TEST(REQUIRE, is_same_v<O3, E3>);
}
}
}

View File

@ -0,0 +1,305 @@
#include <catch.hpp>
#include <pfor/expression/expression.h>
#include <pfor/expression/operators.h>
#include <pfor/mp/meta.h>
#define N 5
TEST_CASE("Expression") {
int a[]{1000, 2000, 3000, 4000, 5000},
ca[]{1000, 2000, 3000, 4000, 5000},
b[]{9, 8, 7, 6, 5},
*pa[]{a+0, a+1, a+2, a+3, a+4};
pfor::expr::Expression<int*, pfor::UIntToType<1>, pfor::Index> ea{a};
pfor::expr::Expression<int*, pfor::UIntToType<2>, pfor::Index> eb{b};
pfor::expr::Expression<int**, pfor::UIntToType<3>, pfor::Index> epa{pa};
SECTION("Expression") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE(ea[i] == a[i]);
REQUIRE(eb[i] == b[i]);
}
}
SECTION("Basic operations") {
SECTION("Unary") {
SECTION("PostIncr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea++)[i] == (ca[i]));
REQUIRE(a[i] == (ca[i]+1));
}
}
SECTION("PostDecr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea--)[i] == (ca[i]));
REQUIRE(a[i] == (ca[i]-1));
}
}
SECTION("PreIncr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((++ea)[i] == (ca[i]+1));
REQUIRE(a[i] == (ca[i]+1));
}
}
SECTION("PreDecr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((--ea)[i] == (ca[i]-1));
REQUIRE(a[i] == (ca[i]-1));
}
}
SECTION("Plus") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((+ea)[i] == (ca[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Minus") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((-ea)[i] == (-ca[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Not") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((!ea)[i] == (!ca[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("BitNot") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((~ea)[i] == (~ca[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Indirection") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((*epa)[i] == (a[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("AddressOf") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((&ea)[i] == (a+i));
REQUIRE(a[i] == (ca[i]));
}
}
}
SECTION("Binary") {
SECTION("Multiplication") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea*eb)[i] == (a[i]*b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Division") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea/eb)[i] == (a[i]/b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Modulo") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea%eb)[i] == (a[i]%b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Addition") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea+eb)[i] == (a[i]+b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Subtraction") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea-eb)[i] == (a[i]-b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("LeftShift") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea<<eb)[i] == (a[i]<<b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("RightShift") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea>>eb)[i] == (a[i]>>b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Lower") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea<eb)[i] == (a[i]<b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("LowerEqual") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea<=eb)[i] == (a[i]<=b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Greater") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea>eb)[i] == (a[i]>b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("GreaterEqual") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea>=eb)[i] == (a[i]>=b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Equal") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea==eb)[i] == (a[i]==b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("NotEqual") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea!=eb)[i] == (a[i]!=b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("BitAnd") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea&eb)[i] == (a[i]&b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("BitXor") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea^eb)[i] == (a[i]^b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("BitOr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea|eb)[i] == (a[i]|b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("And") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea&&eb)[i] == (a[i]&&b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Or") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea||eb)[i] == (a[i]||b[i]));
REQUIRE(a[i] == (ca[i]));
}
}
SECTION("Assignments") {
SECTION("Assign") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea=eb)[i] == (a[i]=b[i]));
REQUIRE(a[i] == b[i]);
}
}
SECTION("AssignAdd") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea+=eb)[i] == (a[i]+b[i]));
REQUIRE(a[i] == (ca[i]+b[i]));
}
}
SECTION("AssignSub") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea-=eb)[i] == (a[i]-b[i]));
REQUIRE(a[i] == (ca[i]-b[i]));
}
}
SECTION("AssignMul") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea*=eb)[i] == (a[i]*b[i]));
REQUIRE(a[i] == (ca[i]*b[i]));
}
}
SECTION("AssignDiv") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea/=eb)[i] == (a[i]/b[i]));
REQUIRE(a[i] == (ca[i]/b[i]));
}
}
SECTION("AssignMod") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea%=eb)[i] == (a[i]%b[i]));
REQUIRE(a[i] == (ca[i]%b[i]));
}
}
SECTION("AssignLS") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea<<=eb)[i] == (a[i]<<b[i]));
REQUIRE(a[i] == (ca[i]<<b[i]));
}
}
SECTION("AssignRS") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea>>=eb)[i] == (a[i]>>b[i]));
REQUIRE(a[i] == (ca[i]>>b[i]));
}
}
SECTION("AssignAnd") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea&=eb)[i] == (a[i]&b[i]));
REQUIRE(a[i] == (ca[i]&b[i]));
}
}
SECTION("AssignXor") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea^=eb)[i] == (a[i]^b[i]));
REQUIRE(a[i] == (ca[i]^b[i]));
}
}
SECTION("AssignOr") {
for(std::size_t i = 0; i < N; ++i) {
REQUIRE((ea|=eb)[i] == (a[i]|b[i]));
REQUIRE(a[i] == (ca[i]|b[i]));
}
}
}
}
}
}

403
tests/expression/op.cpp Normal file
View File

@ -0,0 +1,403 @@
#include <catch.hpp>
#include <pfor/expression/expression.h>
template<typename T>
struct Value {
using IsExpression = pfor::expr::tag::Expression;
T* ptr;
Value(T& v): ptr{&v} {}
T& eval() { return *ptr; }
};
template<typename T, std::size_t N>
struct Array {
using IsExpression = pfor::expr::tag::Expression;
T* ptr;
Array(T* v): ptr{v} {}
T& operator[](std::size_t i) { return ptr[i]; }
};
TEST_CASE("operations") {
int a = 240, b = 3;
int *pa = &a, *pb = &b;
int t[5]{100, 200, 300, 400, 500}, u[5]{1, 2, 3, 4, 5};
int *ps[]{pa, pb};
Value<int> va{a}, vb{b};
Value<int*> vpa{pa}, vpb{pb};
Array<int, 5> at{t}, au{u};
Array<int*, 2> aps{ps};
int i3{3};
Value<int> v3{i3};
SECTION("unary operators") {
SECTION("PostIncr") {
int a_{a}, b_{b}, t3{t[3]};
pfor::expr::op::PostIncr o;
REQUIRE(o.eval(va) == a_);
REQUIRE(a == a_+1);
REQUIRE(o.eval(vb) == b_);
REQUIRE(b == b_+1);
REQUIRE(o.eval(3, at) == t3);
REQUIRE(t[3] == t3+1);
}
SECTION("PostDecr") {
int a_{a}, b_{b}, t3{t[3]};
pfor::expr::op::PostDecr o;
REQUIRE(o.eval(va) == a_);
REQUIRE(a == a_-1);
REQUIRE(o.eval(vb) == b_);
REQUIRE(b == b_-1);
REQUIRE(o.eval(3, at) == t3);
REQUIRE(t[3] == t3-1);
}
SECTION("PreIncr") {
int a_{a}, b_{b}, t3{t[3]};
pfor::expr::op::PreIncr o;
REQUIRE(o.eval(va) == a_+1);
REQUIRE(o.eval(vb) == b_+1);
REQUIRE(o.eval(3, at) == t3+1);
}
SECTION("PreDecr") {
int a_{a}, b_{b}, t3{t[3]};
pfor::expr::op::PreDecr o;
REQUIRE(o.eval(va) == a_-1);
REQUIRE(o.eval(vb) == b_-1);
REQUIRE(o.eval(3, at) == t3-1);
}
SECTION("Plus") {
pfor::expr::op::Plus o;
REQUIRE(o.eval(va) == a);
REQUIRE(o.eval(vb) == b);
REQUIRE(o.eval(3, at) == t[3]);
}
SECTION("Minus") {
pfor::expr::op::Minus o;
REQUIRE(o.eval(va) == -a);
REQUIRE(o.eval(vb) == -b);
REQUIRE(o.eval(3, at) == -t[3]);
}
SECTION("Not") {
pfor::expr::op::Not o;
REQUIRE_FALSE(o.eval(va));
REQUIRE_FALSE(o.eval(vb));
REQUIRE_FALSE(o.eval(3, at));
}
SECTION("BitNot") {
pfor::expr::op::BitNot o;
REQUIRE(o.eval(va) == ~a);
REQUIRE(o.eval(vb) == ~b);
REQUIRE(o.eval(3, at) == ~t[3]);
}
SECTION("Indirection") {
pfor::expr::op::Indirection o;
REQUIRE(o.eval(vpa) == a);
REQUIRE(o.eval(1, aps) == b);
}
SECTION("AddressOf") {
pfor::expr::op::AddressOf o;
REQUIRE(o.eval(va) == &a);
REQUIRE(o.eval(3, at) == t+3);
}
}
SECTION("binary operators") {
SECTION("PtrToMem") {
struct Foo {
int bar = 42;
} foo;
Value<decltype(&Foo::bar) const> vm{&Foo::bar};
Value<Foo*const> vf{&foo};
decltype(&Foo::bar) const tm[]{&Foo::bar};
Foo*const tf[]{&foo};
Array<decltype(&Foo::bar) const, 1> am{tm};
Array<Foo*const, 1> af{tf};
pfor::expr::op::PtrToMem o;
// TODO fix segfault in release
// REQUIRE(o.eval(vf, vm) == 42);
// REQUIRE(o.eval(0, af, am) == 42);
}
SECTION("Multiplication") {
pfor::expr::op::Multiplication o;
REQUIRE(o.eval(va, vb) == a*b);
REQUIRE(o.eval(3, at, au) == t[3]*u[3]);
}
SECTION("Division") {
pfor::expr::op::Division o;
REQUIRE(o.eval(va, vb) == a/b);
REQUIRE(o.eval(3, at, au) == t[3]/u[3]);
}
SECTION("Modulo") {
pfor::expr::op::Modulo o;
REQUIRE(o.eval(va, vb) == a%b);
REQUIRE(o.eval(3, at, au) == t[3]%u[3]);
}
SECTION("Addition") {
pfor::expr::op::Addition o;
REQUIRE(o.eval(va, vb) == a+b);
REQUIRE(o.eval(3, at, au) == t[3]+u[3]);
}
SECTION("Subtraction") {
pfor::expr::op::Subtraction o;
REQUIRE(o.eval(va, vb) == a-b);
REQUIRE(o.eval(3, at, au) == t[3]-u[3]);
}
SECTION("LeftShift") {
pfor::expr::op::LeftShift o;
REQUIRE(o.eval(va, vb) == a<<b);
REQUIRE(o.eval(3, at, au) == t[3]<<u[3]);
}
SECTION("RightShift") {
pfor::expr::op::RightShift o;
REQUIRE(o.eval(va, vb) == a>>b);
REQUIRE(o.eval(3, at, au) == t[3]>>u[3]);
}
SECTION("Lower") {
pfor::expr::op::Lower o;
REQUIRE(o.eval(va, vb) == a<b);
REQUIRE(o.eval(3, at, au) == t[3]<u[3]);
}
SECTION("LowerEqual") {
pfor::expr::op::LowerEqual o;
REQUIRE(o.eval(va, vb) == a<=b);
REQUIRE(o.eval(3, at, au) == t[3]<=u[3]);
}
SECTION("Greater") {
pfor::expr::op::Greater o;
REQUIRE(o.eval(va, vb) == a>b);
REQUIRE(o.eval(3, at, au) == t[3]>u[3]);
}
SECTION("GreaterEqual") {
pfor::expr::op::GreaterEqual o;
REQUIRE(o.eval(va, vb) == a>=b);
REQUIRE(o.eval(3, at, au) == t[3]>=u[3]);
}
SECTION("Equal") {
pfor::expr::op::Equal o;
REQUIRE(o.eval(va, vb) == (a==b));
REQUIRE(o.eval(3, at, au) == (t[3]==u[3]));
}
SECTION("NotEqual") {
pfor::expr::op::NotEqual o;
REQUIRE(o.eval(va, vb) == (a!=b));
REQUIRE(o.eval(3, at, au) == (t[3]!=u[3]));
}
SECTION("BitAnd") {
pfor::expr::op::BitAnd o;
REQUIRE(o.eval(va, vb) == (a&b));
REQUIRE(o.eval(3, at, au) == (t[3]&u[3]));
}
SECTION("BitXor") {
pfor::expr::op::BitXor o;
REQUIRE(o.eval(va, vb) == (a^b));
REQUIRE(o.eval(3, at, au) == (t[3]^u[3]));
}
SECTION("BitOr") {
pfor::expr::op::BitOr o;
REQUIRE(o.eval(va, vb) == (a|b));
REQUIRE(o.eval(3, at, au) == (t[3]|u[3]));
}
SECTION("And") {
pfor::expr::op::And o;
REQUIRE(o.eval(va, vb) == (a&&b));
REQUIRE(o.eval(3, at, au) == (t[3]&&u[3]));
}
SECTION("Or") {
pfor::expr::op::Or o;
REQUIRE(o.eval(va, vb) == (a||b));
REQUIRE(o.eval(3, at, au) == (t[3]||u[3]));
}
SECTION("Assign") {
pfor::expr::op::Assign o;
REQUIRE(o.eval(va, vb) == (a=b));
REQUIRE(o.eval(3, at, au) == (t[3]=u[3]));
}
SECTION("AssignAdd") {
pfor::expr::op::AssignAdd o;
REQUIRE(o.eval(va, vb) == (a+=b));
REQUIRE(o.eval(3, at, au) == (t[3]+=u[3]));
}
SECTION("AssignSub") {
pfor::expr::op::AssignSub o;
REQUIRE(o.eval(va, vb) == (a-=b));
REQUIRE(o.eval(3, at, au) == (t[3]-=u[3]));
}
SECTION("AssignMul") {
pfor::expr::op::AssignMul o;
REQUIRE(o.eval(va, vb) == (a*=b));
REQUIRE(o.eval(3, at, au) == (t[3]*=u[3]));
}
SECTION("AssignDiv") {
pfor::expr::op::AssignDiv o;
REQUIRE(o.eval(va, vb) == (a/=b));
REQUIRE(o.eval(3, at, au) == (t[3]/=u[3]));
}
SECTION("AssignMod") {
pfor::expr::op::AssignMod o;
REQUIRE(o.eval(va, vb) == (a%=b));
REQUIRE(o.eval(3, at, au) == (t[3]%=u[3]));
}
SECTION("AssignLS") {
pfor::expr::op::AssignLS o;
REQUIRE(o.eval(va, vb) == (a<<=b));
REQUIRE(o.eval(3, at, au) == (t[3]<<=u[3]));
}
SECTION("AssignRS") {
pfor::expr::op::AssignRS o;
REQUIRE(o.eval(va, vb) == (a>>=b));
REQUIRE(o.eval(3, at, au) == (t[3]>>=u[3]));
}
SECTION("AssignAnd") {
pfor::expr::op::AssignAnd o;
REQUIRE(o.eval(va, vb) == (a&=b));
REQUIRE(o.eval(3, at, au) == (t[3]&=u[3]));
}
SECTION("AssignXor") {
pfor::expr::op::AssignXor o;
REQUIRE(o.eval(va, vb) == (a^=b));
REQUIRE(o.eval(3, at, au) == (t[3]^=u[3]));
}
SECTION("AssignOr") {
pfor::expr::op::AssignOr o;
REQUIRE(o.eval(va, vb) == (a|=b));
REQUIRE(o.eval(3, at, au) == (t[3]|=u[3]));
}
SECTION("Comma") {
pfor::expr::op::Comma o;
REQUIRE(o.eval(va, vb) == b);
REQUIRE(o.eval(3, at, au) == au[3]);
REQUIRE(o.eval(va, va, vb) == b);
REQUIRE(o.eval(3, at, at, au) == au[3]);
}
}
SECTION("If") {
pfor::expr::op::If o;
REQUIRE(o.eval(va, va, vb) == a);
REQUIRE(o.eval(3, at, at, au) == t[3]);
}
SECTION("FunctionCall") {
auto f1 = []{ return 42; };
auto f2 = [](int i, int j) { return std::to_string(i/2+j); };
decltype(f2) tf2[]{f2};
Array<decltype(f2), 1> atf2{tf2};
pfor::expr::op::FunctionCall o;
REQUIRE(o.eval(Value<decltype(f1)>{f1}) == 42);
REQUIRE(o.eval(0, atf2, at, au) == "51");
}
SECTION("Subscript") {
pfor::expr::op::Subscript o;
int i{1};
int id[]{1, 0};
int a[]{3, 2, 1, 0};
int a2[][2]{{3, 2}, {1, 4}};
Value<int> vi{i};
Value<int[4]> va{a};
Array<int, 4> ai{id};
Array<int[2], 4> aa{a2};
REQUIRE(o.eval(va, vi) == a[i]);
REQUIRE(o.eval(1, aa, ai) == a2[1][id[1]]);
}
}

132
tests/expression/tagger.cpp Normal file
View File

@ -0,0 +1,132 @@
#include <catch.hpp>
#include "../common.h"
#include <pfor/expression/tagger.h>
#include <pfor/expression/operators.h>
TEST_CASE("ExpressionTagger") {
constexpr pfor::expr::Access R = pfor::expr::Access::read, W = pfor::expr::Access::write;
using O1 = pfor::expr::Expression<int*, class IDa, pfor::Index>;
using O2 = pfor::expr::Expression<int*, class IDb, pfor::Index>;
using O3 = pfor::expr::Expression<int*, class IDc, pfor::Index>;
using OT1R = pfor::expr::OperandTag<class IDa, R, pfor::Index>;
using OT2R = pfor::expr::OperandTag<class IDb, R, pfor::Index>;
using OT3R = pfor::expr::OperandTag<class IDc, R, pfor::Index>;
using OT1W = pfor::expr::OperandTag<class IDa, W, pfor::Index>;
using OT2W = pfor::expr::OperandTag<class IDb, W, pfor::Index>;
using OT3W = pfor::expr::OperandTag<class IDc, W, pfor::Index>;
using Tags1R = pfor::Pack<OT1R>;
using Tags1R2R = pfor::Pack<OT1R, OT2R>;
using Tags1R2R3R = pfor::Pack<OT1R, OT2R, OT3R>;
using Tags1W2R = pfor::Pack<OT1W, OT2R>;
using Tags1W1R2R = pfor::Pack<OT1W, OT1R, OT2R>;
using Tags1W1R2R3R = pfor::Pack<OT1W, OT1R, OT2R, OT3R>;
using Tags1W2W3R3R = pfor::Pack<OT1W, OT2W, OT3R, OT3R>;
using Tags1R2W3W3R = pfor::Pack<OT1R, OT2W, OT3W, OT3R>;
using Tags1R2W3R3R = pfor::Pack<OT1R, OT2W, OT3R, OT3R>;
using EPlus = decltype(+V(O1));
using EMinus = decltype(-V(O1));
using ENot = decltype(!V(O1));
using EBitNot = decltype(~V(O1));
using EIndirection = decltype(*V(O1));
using EAddressOf = decltype(&V(O1));
using EMultiplication = decltype(V(O1) * V(O2));
using EDivision = decltype(V(O1) / V(O2));
using EModulo = decltype(V(O1) % V(O2));
using EAddition = decltype(V(O1) + V(O2));
using ESubtraction = decltype(V(O1) - V(O2));
using ELeftShift = decltype(V(O1) << V(O2));
using ERightShift = decltype(V(O1) >> V(O2));
using ELower = decltype(V(O1) < V(O2));
using ELowerEqual = decltype(V(O1) <= V(O2));
using EGreater = decltype(V(O1) > V(O2));
using EGreaterEqual = decltype(V(O1) >= V(O2));
using EEqual = decltype(V(O1) == V(O2));
using ENotEqual = decltype(V(O1) != V(O2));
using EBitAnd = decltype(V(O1) & V(O2));
using EBitXor = decltype(V(O1) ^ V(O2));
using EBitOr = decltype(V(O1) | V(O2));
using EAnd = decltype(V(O1) && V(O2));
using EOr = decltype(V(O1) || V(O2));
using EAssign = decltype(V(O1) = V(O2));
using EAssignAdd = decltype(V(O1) += V(O2));
using EAssignSub = decltype(V(O1) -= V(O2));
using EAssignMul = decltype(V(O1) *= V(O2));
using EAssignDiv = decltype(V(O1) /= V(O2));
using EAssignMod = decltype(V(O1) %= V(O2));
using EAssignLS = decltype(V(O1) <<= V(O2));
using EAssignRS = decltype(V(O1) >>= V(O2));
using EAssignAnd = decltype(V(O1) &= V(O2));
using EAssignXor = decltype(V(O1) ^= V(O2));
using EAssignOr = decltype(V(O1) |= V(O2));
using E1Assign1Add = decltype(V(O1) = V(O1) + V(O2));
using E1Assign2Add = decltype(V(O1) = V(O1) + V(O2) + V(O3));
using E2Assign1Add = decltype(V(O1) = V(O2) = V(O3) + V(O3));
using EIf = decltype(If(V(O1), V(O2), V(O3)));
using EIfAssign = decltype(If(V(O1), V(O2), V(O3)) = V(O3));
using EIfInAssign = decltype(If(V(O1), V(O2) = V(O3), V(O3)));
SECTION("ExpressionTagger") {
SECTION("Unary operations") {
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EPlus>, Tags1R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EMinus>, Tags1R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ENot>, Tags1R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EBitNot>, Tags1R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EIndirection>, Tags1R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAddressOf>, Tags1R>);
}
SECTION("Binary operations") {
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EMultiplication>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EDivision>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EModulo>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAddition>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ESubtraction>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ELeftShift>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ERightShift>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ELower>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ELowerEqual>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EGreater>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EGreaterEqual>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EEqual>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<ENotEqual>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EBitAnd>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EBitXor>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EBitOr>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAnd>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EOr>, Tags1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssign>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignAdd>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignSub>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignMul>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignDiv>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignMod>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignLS>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignRS>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignAnd>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignXor>, Tags1W2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EAssignOr>, Tags1W2R>);
}
SECTION("If") {
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EIf>, Tags1R2R3R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EIfAssign>, Tags1R2W3W3R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<EIfInAssign>, Tags1R2W3R3R>);
}
SECTION("Multiple operations") {
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<E1Assign1Add>, Tags1W1R2R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<E1Assign2Add>, Tags1W1R2R3R>);
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionTagger<E2Assign1Add>, Tags1W2W3R3R>);
}
}
}

View File

@ -0,0 +1,33 @@
#include <catch.hpp>
#include "../common.h"
#include <pfor/expression/traits.h>
TEST_CASE("Expression/Traits") {
struct E { using IsExpression = pfor::expr::tag::Expression; } e;
struct F {} f;
SECTION("IsExpression") {
REQUIRE(pfor::expr::IsExpression<E>::value);
REQUIRE_FALSE(pfor::expr::IsExpression<F>::value);
REQUIRE(pfor::expr::IsExpression<decltype(e)>::value);
REQUIRE_FALSE(pfor::expr::IsExpression<decltype(f)>::value);
}
SECTION("AllExpression") {
TEST(REQUIRE, pfor::expr::AllExpression<E, E, E, E>::value);
TEST(REQUIRE_FALSE, pfor::expr::AllExpression<E, E, F, E>::value);
TEST(REQUIRE_FALSE, pfor::expr::AllExpression<E, F, F, E>::value);
TEST(REQUIRE_FALSE, pfor::expr::AllExpression<F, F, F, E>::value);
TEST(REQUIRE_FALSE, pfor::expr::AllExpression<F, F, F, F>::value);
}
SECTION("AnyExpression") {
TEST(REQUIRE, pfor::expr::AnyExpression<E, E, E, E>::value);
TEST(REQUIRE, pfor::expr::AnyExpression<E, E, F, E>::value);
TEST(REQUIRE, pfor::expr::AnyExpression<E, F, F, E>::value);
TEST(REQUIRE, pfor::expr::AnyExpression<F, F, F, E>::value);
TEST(REQUIRE_FALSE, pfor::expr::AnyExpression<F, F, F, F>::value);
}
}