thesis version
This commit is contained in:
325
tests/cluster.cpp
Normal file
325
tests/cluster.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
#include <catch.hpp>
|
||||
#include "common.h"
|
||||
|
||||
#include <pfor/clusters.h>
|
||||
#include <pfor/expression/operand.h>
|
||||
#include <pfor/expression/operators.h>
|
||||
|
||||
#define N 10
|
||||
|
||||
TEST_CASE("Cluster") {
|
||||
int a_[N], b_[N], c_[N], d_[N], e_[N], f_[N], g_[N];
|
||||
|
||||
auto a = pfor::Operand<int*, class IDa>(a_);
|
||||
auto b = pfor::Operand<int*, class IDb>(b_);
|
||||
auto c = pfor::Operand<int*, class IDc>(c_);
|
||||
auto d = pfor::Operand<int*, class IDd>(d_);
|
||||
auto e = pfor::Operand<int*, class IDe>(e_);
|
||||
auto f = pfor::Operand<int*, class IDf>(f_);
|
||||
auto g = pfor::Operand<int*, class IDg>(g_);
|
||||
|
||||
using UE0 = decltype(a+b);
|
||||
using UE1 = decltype(d = b+c);
|
||||
using UE2 = decltype(e = g);
|
||||
using UE3 = decltype(b = a);
|
||||
using UE4 = decltype(f = f+f);
|
||||
using UE5 = decltype(g = f);
|
||||
using UE6 = decltype(c = d);
|
||||
using UE7 = decltype(g = b);
|
||||
|
||||
using E0 = std::decay_t<decltype(V(UE0))>;
|
||||
using E1 = std::decay_t<decltype(V(UE1))>;
|
||||
using E2 = std::decay_t<decltype(V(UE1), V(UE2))>;
|
||||
using E3 = std::decay_t<decltype(V(UE1), V(UE2), V(UE3))>;
|
||||
using E4 = std::decay_t<decltype(V(UE4), V(UE5), V(UE6))>;
|
||||
using E5 = std::decay_t<decltype(V(UE1), V(UE2), V(UE4), V(UE6))>;
|
||||
using E6 = std::decay_t<decltype(V(UE2), V(UE3), V(UE4), V(UE7), V(UE6))>;
|
||||
|
||||
using S0 = pfor::Pack<UE0>;
|
||||
using S1 = pfor::Pack<UE1>;
|
||||
using S2 = pfor::Pack<UE1, UE2>;
|
||||
using S3 = pfor::Pack<UE1, UE2, UE3>;
|
||||
using S4 = pfor::Pack<UE4, UE5, UE6>;
|
||||
using S5 = pfor::Pack<UE1, UE2, UE4, UE6>;
|
||||
|
||||
SECTION("SplitComma") {
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E0>, S0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E1>, S1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E2>, S2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E3>, S3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E4>, S4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::SplitComma<E5>, S5>);
|
||||
}
|
||||
|
||||
SECTION("ReadList") {
|
||||
using R0 = pfor::Pack<class IDa, class IDb>;
|
||||
using R1 = pfor::Pack<class IDb, class IDc>;
|
||||
using R2 = pfor::Pack<class IDb, class IDc, class IDg>;
|
||||
using R3 = pfor::Pack<class IDb, class IDc, class IDg, class IDa>;
|
||||
using R4 = pfor::Pack<class IDf, class IDf, class IDf, class IDd>;
|
||||
using R5 = pfor::Pack<class IDb, class IDc, class IDg, class IDf, class IDf, class IDd>;
|
||||
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E0>>, R0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E1>>, R1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E2>>, R2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E3>>, R3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E4>>, R4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ReadList<pfor::expr::ExpressionTagger<E5>>, R5>);
|
||||
}
|
||||
|
||||
SECTION("WriteList") {
|
||||
using W0 = pfor::Pack<>;
|
||||
using W1 = pfor::Pack<class IDd>;
|
||||
using W2 = pfor::Pack<class IDd, class IDe>;
|
||||
using W3 = pfor::Pack<class IDd, class IDe, class IDb>;
|
||||
using W4 = pfor::Pack<class IDf, class IDg, class IDc>;
|
||||
using W5 = pfor::Pack<class IDd, class IDe, class IDf, class IDc>;
|
||||
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E0>>, W0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E1>>, W1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E2>>, W2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E3>>, W3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E4>>, W4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::WriteList<pfor::expr::ExpressionTagger<E5>>, W5>);
|
||||
}
|
||||
|
||||
SECTION("ComparatorUIntToType") {
|
||||
TEST(REQUIRE, pfor::ComparatorUIntToType<pfor::UIntToType<0>, pfor::UIntToType<1>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntToType<pfor::UIntToType<0>, pfor::UIntToType<0>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntToType<pfor::UIntToType<1>, pfor::UIntToType<0>>::value);
|
||||
}
|
||||
|
||||
SECTION("ComparatorUIntPack") {
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<>, UIntsToPack<>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<0>, UIntsToPack<>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<0, 1>, UIntsToPack<>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<1>, UIntsToPack<0>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<1>, UIntsToPack<0, 1, 2>>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorUIntPack<UIntsToPack<2>, UIntsToPack<0, 1, 2>>::value);
|
||||
|
||||
TEST(REQUIRE, pfor::ComparatorUIntPack<UIntsToPack<>, UIntsToPack<1>>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorUIntPack<UIntsToPack<0>, UIntsToPack<1>>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorUIntPack<UIntsToPack<0, 1, 2>, UIntsToPack<1>>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorUIntPack<UIntsToPack<0, 1, 2>, UIntsToPack<1, 3>>::value);
|
||||
|
||||
TEST(REQUIRE, pfor::ComparatorUIntPack<UIntsToPack<1, 2>, UIntsToPack<1, 3>>::value);
|
||||
}
|
||||
|
||||
SECTION("ComparatorExpressionInfo") {
|
||||
using C0 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<>, UIntsToPack<>>;
|
||||
using C1 = pfor::Pack<pfor::UIntToType<1>, UIntsToPack<>, UIntsToPack<>>;
|
||||
using C2 = pfor::Pack<pfor::UIntToType<2>, UIntsToPack<>, UIntsToPack<>>;
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C0, C0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C1, C0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C1, C1>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C2, C0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C2, C1>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorExpressionInfo<C2, C2>::value);
|
||||
|
||||
TEST(REQUIRE, pfor::ComparatorExpressionInfo<C0, C1>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorExpressionInfo<C0, C2>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorExpressionInfo<C1, C2>::value);
|
||||
}
|
||||
|
||||
SECTION("ComparatorWritePack") {
|
||||
using WP0 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<>, UIntsToPack<>>;
|
||||
using WP1 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<0>, UIntsToPack<>>;
|
||||
using WP2 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<1>, UIntsToPack<>>;
|
||||
using WP3 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<0, 1, 2>, UIntsToPack<>>;
|
||||
using WP4 = pfor::Pack<pfor::UIntToType<0>, UIntsToPack<0, 2>, UIntsToPack<>>;
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP0, WP0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP1, WP0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP2, WP0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP3, WP1>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP4, WP1>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ComparatorWritePack<WP4, WP3>::value);
|
||||
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP0, WP1>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP0, WP2>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP1, WP2>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP3, WP2>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP4, WP2>::value);
|
||||
TEST(REQUIRE, pfor::ComparatorWritePack<WP3, WP4>::value);
|
||||
}
|
||||
|
||||
SECTION("ExpressionInfo") {
|
||||
using EI0 = pfor::Pack<pfor::Pack<pfor::UIntToType<0>, pfor::Pack<>, pfor::Pack<class IDa, class IDb>>>;
|
||||
using EI1 = pfor::Pack<pfor::Pack<pfor::UIntToType<0>, pfor::Pack<class IDd>, pfor::Pack<class IDb, class IDc>>>;
|
||||
using EI2 = pfor::Pack<
|
||||
pfor::Pack<pfor::UIntToType<0>, pfor::Pack<class IDd>, pfor::Pack<class IDb, class IDc>>,
|
||||
pfor::Pack<pfor::UIntToType<1>, pfor::Pack<class IDe>, pfor::Pack<class IDg>>
|
||||
>;
|
||||
using EI3 = pfor::Pack<
|
||||
pfor::Pack<pfor::UIntToType<0>, pfor::Pack<class IDd>, pfor::Pack<class IDb, class IDc>>,
|
||||
pfor::Pack<pfor::UIntToType<1>, pfor::Pack<class IDe>, pfor::Pack<class IDg>>,
|
||||
pfor::Pack<pfor::UIntToType<2>, pfor::Pack<class IDb>, pfor::Pack<class IDa>>
|
||||
>;
|
||||
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionInfo<S0>, EI0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionInfo<S1>, EI1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionInfo<S2>, EI2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::expr::ExpressionInfo<S3>, EI3>);
|
||||
}
|
||||
|
||||
SECTION("Clusters") {
|
||||
using C0 = pfor::Pack<>;
|
||||
using C1 = pfor::expr::ExpressionInfo<S1>;
|
||||
using C2 = pfor::expr::ExpressionInfo<S2>;
|
||||
using C3 = pfor::expr::ExpressionInfo<S3>;
|
||||
using C4 = pfor::expr::ExpressionInfo<S4>;
|
||||
using C5 = pfor::expr::ExpressionInfo<S5>;
|
||||
|
||||
using CC0 = pfor::Pack<>;
|
||||
using CC1 = pfor::Pack<C1>;
|
||||
using CC2 = pfor::Pack<C2>;
|
||||
using CC3 = pfor::Pack<C3>;
|
||||
using CC4 = pfor::Pack<C4>;
|
||||
using CC5 = pfor::Pack<C5>;
|
||||
|
||||
using I0 = pfor::Pack<pfor::UIntToType<0>, pfor::Pack<>, pfor::Pack<>>;
|
||||
using I1 = pfor::Pack<pfor::UIntToType<1>, pfor::Pack<class IDg, class IDh>, pfor::Pack<class IDh, class IDi>>;
|
||||
using I2 = pfor::Pack<pfor::UIntToType<2>, pfor::Pack<class IDd, class IDh>, pfor::Pack<class IDb, class IDh, class IDi>>;
|
||||
using I3 = pfor::Pack<pfor::UIntToType<3>, pfor::Pack<class IDi>, pfor::Pack<class IDa, class IDf, class IDg, class IDh, class IDi>>;
|
||||
|
||||
using CC0I1 = pfor::Pack<pfor::Pack<I1>>;
|
||||
using CC0I2 = pfor::Pack<pfor::Pack<I2>>;
|
||||
using CC1I1 = pfor::Pack<C1, pfor::Pack<I1>>;
|
||||
using CC1I2 = pfor::Pack<pfor::PackSortInsert<pfor::ComparatorExpressionInfo, C1, I2>>;
|
||||
using CC2I1 = pfor::Pack<pfor::PackSortInsert<pfor::ComparatorExpressionInfo, C2, I1>>;
|
||||
using CC2I2 = pfor::Pack<pfor::PackSortInsert<pfor::ComparatorExpressionInfo, C2, I2>>;
|
||||
|
||||
using F0 = UIntsToPack<>;
|
||||
using F1 = UIntsToPack<0>;
|
||||
using F2 = UIntsToPack<0, 1>;
|
||||
using F3 = UIntsToPack<0, 1, 2>;
|
||||
using F4 = UIntsToPack<0, 1, 2>;
|
||||
using F5 = UIntsToPack<0, 1, 2, 3>;
|
||||
|
||||
using CF0 = pfor::Pack<>;
|
||||
using CF1 = pfor::Pack<F1>;
|
||||
using CF2 = pfor::Pack<F2>;
|
||||
using CF3 = pfor::Pack<F3>;
|
||||
using CF4 = pfor::Pack<F4>;
|
||||
using CF5 = pfor::Pack<F5>;
|
||||
|
||||
using CF1I1 = pfor::Pack<UIntsToPack<0>, UIntsToPack<1>>;
|
||||
|
||||
// using CE0 = pfor::Pack<>;
|
||||
// using CE1 = UIntsToPack<0>;
|
||||
// using CE2 = UIntsToPack<0, 1>;
|
||||
// using CE3 = UIntsToPack<0, 1, 2>;
|
||||
// using CE4 = UIntsToPack<0, 1, 2>;
|
||||
// using CE5 = UIntsToPack<0, 1, 2, 3>;
|
||||
|
||||
// using CCE0 = pfor::Pack<>;
|
||||
// using CCE1 = pfor::Pack<CE1>;
|
||||
// using CCE2 = pfor::Pack<CE2>;
|
||||
// using CCE3 = pfor::Pack<CE3>;
|
||||
// using CCE4 = pfor::Pack<CE4>;
|
||||
// using CCE5 = pfor::Pack<CE5>;
|
||||
|
||||
SECTION("ClusterDepends") {
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C0, I0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C0, I1>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C0, I2>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C0, I3>::value);
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C1, I0>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C1, I1>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C1, I2>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C1, I3>::value);
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C2, I0>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C2, I1>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C2, I2>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C2, I3>::value);
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C3, I0>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C3, I1>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C3, I2>::value);
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C3, I3>::value);
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C4, I0>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C4, I1>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C4, I2>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C4, I3>::value);
|
||||
|
||||
TEST(REQUIRE_FALSE, pfor::ClusterDepends<C5, I0>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C5, I1>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C5, I2>::value);
|
||||
TEST(REQUIRE, pfor::ClusterDepends<C5, I3>::value);
|
||||
}
|
||||
|
||||
SECTION("ClustersInsert") {
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC0, I1>, CC0I1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC0, I2>, CC0I2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC1, I1>, CC1I1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC1, I2>, CC1I2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC2, I1>, CC2I1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersInsert<CC2, I2>, CC2I2>);
|
||||
}
|
||||
|
||||
SECTION("ClusterExpressionIds") {
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C0>, F0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C1>, F1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C2>, F2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C3>, F3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C4>, F4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClusterExpressionIds<C5>, F5>);
|
||||
}
|
||||
|
||||
SECTION("ClustersExpressionIds") {
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC0>, CF0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC1>, CF1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC2>, CF2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC3>, CF3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC4>, CF4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC5>, CF5>);
|
||||
|
||||
TEST(REQUIRE, is_same_v<pfor::ClustersExpressionIds<CC1I1>, CF1I1>);
|
||||
}
|
||||
|
||||
// SECTION("ClusterExpression") {
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S0, F0>, CE0>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S1, F1>, CE1>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S2, F2>, CE2>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S3, F3>, CE3>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S4, F4>, CE4>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClusterExpression<S5, F5>, CE5>);
|
||||
// }
|
||||
//
|
||||
// SECTION("ClustersExpression") {
|
||||
// using CCE1I1 = pfor::Pack<UIntsToPack<0>, UIntsToPack<1>>;
|
||||
//
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S0, CF0>, CCE0>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S1, CF1>, CCE1>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S2, CF2>, CCE2>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S3, CF3>, CCE3>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S4, CF4>, CCE4>);
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S5, CF5>, CCE5>);
|
||||
//
|
||||
// TEST(REQUIRE, is_same_v<pfor::ClustersExpression<S5, CF1I1>, CCE1I1>);
|
||||
// }
|
||||
|
||||
SECTION("ClustersGen") {
|
||||
using CG0 = pfor::Pack<UIntsToPack<0>>;
|
||||
using CG1 = pfor::Pack<UIntsToPack<0>>;
|
||||
using CG2 = pfor::Pack<UIntsToPack<0>, UIntsToPack<1>>;
|
||||
using CG3 = pfor::Pack<UIntsToPack<0, 2>, UIntsToPack<1>>;
|
||||
using CG4 = pfor::Pack<UIntsToPack<0, 1>, UIntsToPack<2>>;
|
||||
using CG5 = pfor::Pack<UIntsToPack<0, 3>, UIntsToPack<1>, UIntsToPack<2>>;
|
||||
using CG6 = pfor::Pack<UIntsToPack<0, 1, 3>, UIntsToPack<2>, UIntsToPack<4>>;
|
||||
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E0>::type, CG0>);
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E1>::type, CG1>);
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E2>::type, CG2>);
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E3>::type, CG3>);
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E4>::type, CG4>);
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E5>::type, CG5>);
|
||||
|
||||
TEST(REQUIRE, is_same_v<typename pfor::ClustersGen<E6>::type, CG6>);
|
||||
}
|
||||
}
|
||||
}
|
30
tests/common.h
Normal file
30
tests/common.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef CATCH_COMMON_H
|
||||
#define CATCH_COMMON_H
|
||||
|
||||
#include <pfor/mp/meta.h>
|
||||
#include <pfor/mp/pack.h>
|
||||
#include <pfor/index/index.h>
|
||||
|
||||
#define TEST(T, ...) do { \
|
||||
decltype(__VA_ARGS__) r_ = __VA_ARGS__; \
|
||||
T(r_); \
|
||||
} while(false)
|
||||
|
||||
#define TEST_IF(T, O, R, ...) do { \
|
||||
decltype(__VA_ARGS__) r_ = __VA_ARGS__; \
|
||||
T(r_ O R); \
|
||||
} while(false)
|
||||
|
||||
#define V(T) std::declval<T>()
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr bool is_same_v = std::is_same<T, U>::value;
|
||||
|
||||
template<std::size_t... Is>
|
||||
using UIntsToPack = pfor::Pack<pfor::UIntToType<Is>...>;
|
||||
|
||||
template<std::size_t V>
|
||||
constexpr auto _ = pfor::ctv<V>;
|
||||
|
||||
|
||||
#endif
|
77
tests/expression/algorithm.cpp
Normal file
77
tests/expression/algorithm.cpp
Normal 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>);
|
||||
}
|
||||
}
|
||||
}
|
305
tests/expression/expression.cpp
Normal file
305
tests/expression/expression.cpp
Normal 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
403
tests/expression/op.cpp
Normal 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
132
tests/expression/tagger.cpp
Normal 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>);
|
||||
}
|
||||
}
|
||||
}
|
33
tests/expression/traits.cpp
Normal file
33
tests/expression/traits.cpp
Normal 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);
|
||||
}
|
||||
}
|
68
tests/index/index.cpp
Normal file
68
tests/index/index.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <pfor/index/index.h>
|
||||
#include <pfor/index/operators.h>
|
||||
|
||||
TEST_CASE("Index") {
|
||||
pfor::Index it;
|
||||
pfor::index::Index<3> c3;
|
||||
|
||||
std::size_t i = 5;
|
||||
|
||||
SECTION("Index") {
|
||||
REQUIRE(it.eval(i) == i);
|
||||
}
|
||||
|
||||
SECTION("Basic operations") {
|
||||
SECTION("Plus") {
|
||||
REQUIRE((+it).eval(i) == i);
|
||||
}
|
||||
|
||||
SECTION("Minus") {
|
||||
REQUIRE((-it).eval(i) == -i);
|
||||
}
|
||||
|
||||
// SECTION("Not") {
|
||||
// REQUIRE((!it).eval(i) == !i);
|
||||
// }
|
||||
|
||||
// SECTION("BitNot") {
|
||||
// REQUIRE((~it).eval(i) == ~i);
|
||||
// }
|
||||
|
||||
SECTION("Addition") {
|
||||
REQUIRE((it+c3).eval(i) == i+3);
|
||||
REQUIRE((it+it).eval(i) == i+i);
|
||||
}
|
||||
|
||||
SECTION("Subtraction") {
|
||||
REQUIRE((it-c3).eval(i) == i-3);
|
||||
REQUIRE((it-it).eval(i) == 0);
|
||||
}
|
||||
|
||||
SECTION("Multiplication") {
|
||||
REQUIRE((it*c3).eval(i) == i*3);
|
||||
REQUIRE((it*it).eval(i) == i*i);
|
||||
}
|
||||
|
||||
// SECTION("Division") {
|
||||
// REQUIRE((it/c3).eval(i) == i/3);
|
||||
// REQUIRE((it/it).eval(i) == 1);
|
||||
// }
|
||||
|
||||
// SECTION("Modulo") {
|
||||
// REQUIRE((it%c3).eval(i) == i%3);
|
||||
// REQUIRE((it%it).eval(i) == 0);
|
||||
// }
|
||||
|
||||
// SECTION("LeftShift") {
|
||||
// REQUIRE((it<<c3).eval(i) == i<<3);
|
||||
// REQUIRE((it<<it).eval(i) == i<<i);
|
||||
// }
|
||||
|
||||
// SECTION("RightShift") {
|
||||
// REQUIRE((it>>c3).eval(i) == i>>3);
|
||||
// REQUIRE((it>>it).eval(i) == i>>i);
|
||||
// }
|
||||
}
|
||||
}
|
75
tests/index/traits.cpp
Normal file
75
tests/index/traits.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include <catch.hpp>
|
||||
#include "../common.h"
|
||||
|
||||
#include <pfor/index/traits.h>
|
||||
#include <pfor/index/operators.h>
|
||||
|
||||
TEST_CASE("Index/Traits") {
|
||||
pfor::Index it;
|
||||
pfor::index::Index<2> c2;
|
||||
pfor::index::Index<3> c3;
|
||||
pfor::index::Index<4> c4;
|
||||
pfor::index::Index<5> c5;
|
||||
|
||||
std::size_t i = 5;
|
||||
|
||||
using C2 = decltype(c2);
|
||||
using C3 = decltype(c3);
|
||||
using C4 = decltype(c4);
|
||||
using C5 = decltype(c5);
|
||||
|
||||
using E0 = decltype(it);
|
||||
using E1 = decltype(it+c3);
|
||||
using E2 = decltype(it*c3);
|
||||
using E3 = decltype(it*c3+c5);
|
||||
using E4 = decltype((it+c3)*c5);
|
||||
using E5 = decltype(((it+c3)*c5+c4)*c2);
|
||||
using E6 = decltype(((it+it)+c3)+(c2*it+c5));
|
||||
using E7 = decltype(((c2+c3)*c4)*(it+c5));
|
||||
|
||||
using F1 = decltype(it*it);
|
||||
using F2 = decltype((it+c3)*(it+c2));
|
||||
using F3 = decltype((it*it+c3)*(c2+it*it));
|
||||
|
||||
SECTION("IsConstant") {
|
||||
REQUIRE(pfor::index::isConstant<C2>);
|
||||
REQUIRE(pfor::index::isConstant<C3>);
|
||||
REQUIRE(pfor::index::isConstant<C4>);
|
||||
REQUIRE(pfor::index::isConstant<C5>);
|
||||
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E0>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E1>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E2>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E3>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E4>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E5>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E6>);
|
||||
REQUIRE_FALSE(pfor::index::isConstant<E7>);
|
||||
}
|
||||
|
||||
SECTION("IsLinear") {
|
||||
REQUIRE(pfor::index::isLinear<C2>);
|
||||
REQUIRE(pfor::index::isLinear<C3>);
|
||||
REQUIRE(pfor::index::isLinear<C4>);
|
||||
REQUIRE(pfor::index::isLinear<C5>);
|
||||
|
||||
REQUIRE(pfor::index::isLinear<E0>);
|
||||
REQUIRE(pfor::index::isLinear<E1>);
|
||||
REQUIRE(pfor::index::isLinear<E2>);
|
||||
REQUIRE(pfor::index::isLinear<E3>);
|
||||
REQUIRE(pfor::index::isLinear<E4>);
|
||||
REQUIRE(pfor::index::isLinear<E5>);
|
||||
REQUIRE(pfor::index::isLinear<E6>);
|
||||
REQUIRE(pfor::index::isLinear<E7>);
|
||||
|
||||
REQUIRE_FALSE(pfor::index::isLinear<F1>);
|
||||
REQUIRE_FALSE(pfor::index::isLinear<F2>);
|
||||
REQUIRE_FALSE(pfor::index::isLinear<F3>);
|
||||
}
|
||||
|
||||
SECTION("AllLinear") {
|
||||
TEST(REQUIRE, pfor::index::allLinear<C2, C3, C4, C5>);
|
||||
TEST(REQUIRE, pfor::index::allLinear<E0, E1, E2, E3, E4, E5, E6, E7>);
|
||||
TEST(REQUIRE_FALSE, pfor::index::allLinear<E0, E1, E2, F1, E3, E4, E5, E6>);
|
||||
}
|
||||
}
|
88
tests/internal/rwcontrol.cpp
Normal file
88
tests/internal/rwcontrol.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <catch.hpp>
|
||||
#include "../common.h"
|
||||
|
||||
#include <pfor/parallelizable.h>
|
||||
#include <pfor/index/operators.h>
|
||||
|
||||
TEST_CASE("RWControl") {
|
||||
constexpr pfor::expr::Access R = pfor::expr::Access::read, W = pfor::expr::Access::write;
|
||||
|
||||
pfor::Index it;
|
||||
|
||||
using OT1R = pfor::expr::OperandTag<class ID1, R, pfor::Index>;
|
||||
using OT2R = pfor::expr::OperandTag<class ID2, R, pfor::Index>;
|
||||
using OT3R = pfor::expr::OperandTag<class ID3, R, pfor::Index>;
|
||||
using OT1W = pfor::expr::OperandTag<class ID1, W, pfor::Index>;
|
||||
using OT2W = pfor::expr::OperandTag<class ID2, W, pfor::Index>;
|
||||
using OT3W = pfor::expr::OperandTag<class ID3, 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>;
|
||||
|
||||
SECTION("RWControl") {
|
||||
SECTION("Constant index") {
|
||||
using C0 = decltype(pfor::ctv<0>);
|
||||
|
||||
using TagsW = pfor::Pack<pfor::expr::OperandTag<class ID0, W, C0>>;
|
||||
using TagsR = pfor::Pack<pfor::expr::OperandTag<class ID0, R, C0>>;
|
||||
using TagsRW = pfor::Pack<pfor::expr::OperandTag<class ID0, R, C0>, pfor::expr::OperandTag<class ID0, W, C0>>;
|
||||
|
||||
REQUIRE_FALSE(pfor::rwControl<TagsW>);
|
||||
REQUIRE(pfor::rwControl<TagsR>);
|
||||
REQUIRE_FALSE(pfor::rwControl<TagsRW>);
|
||||
}
|
||||
|
||||
SECTION("Same index") {
|
||||
REQUIRE(pfor::rwControl<Tags1R>);
|
||||
REQUIRE(pfor::rwControl<Tags1R2R>);
|
||||
REQUIRE(pfor::rwControl<Tags1R2R>);
|
||||
REQUIRE(pfor::rwControl<Tags1R2R3R>);
|
||||
REQUIRE(pfor::rwControl<Tags1W2R>);
|
||||
REQUIRE(pfor::rwControl<Tags1W1R2R>);
|
||||
REQUIRE(pfor::rwControl<Tags1W1R2R3R>);
|
||||
REQUIRE(pfor::rwControl<Tags1W2W3R3R>);
|
||||
REQUIRE(pfor::rwControl<Tags1R2W3W3R>);
|
||||
REQUIRE(pfor::rwControl<Tags1R2W3R3R>);
|
||||
}
|
||||
|
||||
SECTION("Different indices") {
|
||||
using OT1RI = pfor::expr::OperandTag<class ID1, R, decltype(pfor::ctv<2>*it)>;
|
||||
using OT2RI = pfor::expr::OperandTag<class ID2, R, decltype(pfor::ctv<2>*it)>;
|
||||
using OT3RI = pfor::expr::OperandTag<class ID3, R, decltype(pfor::ctv<2>*it)>;
|
||||
using OT1WI = pfor::expr::OperandTag<class ID1, W, decltype(pfor::ctv<2>*it+pfor::ctv<1>)>;
|
||||
using OT2WI = pfor::expr::OperandTag<class ID2, W, decltype(pfor::ctv<2>*it+pfor::ctv<1>)>;
|
||||
using OT3WI = pfor::expr::OperandTag<class ID3, W, decltype(pfor::ctv<2>*it+pfor::ctv<1>)>;
|
||||
|
||||
using Tags1 = pfor::Pack<OT1RI, OT1WI, OT2RI, OT2WI, OT3RI, OT3WI>;
|
||||
using Tags2 = pfor::Pack<OT1RI, OT1W>;
|
||||
using Tags3 = pfor::Pack<OT1WI, OT1W>;
|
||||
using Tags4 = pfor::Pack<OT1RI, OT1R>;
|
||||
|
||||
REQUIRE(pfor::rwControl<Tags1>);
|
||||
REQUIRE_FALSE(pfor::rwControl<Tags2>);
|
||||
REQUIRE_FALSE(pfor::rwControl<Tags3>);
|
||||
REQUIRE(pfor::rwControl<Tags4>);
|
||||
}
|
||||
|
||||
SECTION("Linear Diophantine Cases") {
|
||||
using LD0 = decltype(pfor::ctv<2>*it);
|
||||
using LD1 = decltype(it+pfor::ctv<5>);
|
||||
using LD2 = decltype(pfor::ctv<2>*it+pfor::ctv<5>);
|
||||
|
||||
using Tags0 = pfor::Pack<pfor::expr::OperandTag<class ID0, R, LD0>, pfor::expr::OperandTag<class ID0, W, LD1>>;
|
||||
using Tags1 = pfor::Pack<pfor::expr::OperandTag<class ID0, R, LD0>, pfor::expr::OperandTag<class ID0, W, LD2>>;
|
||||
using Tags2 = pfor::Pack<pfor::expr::OperandTag<class ID0, R, LD1>, pfor::expr::OperandTag<class ID0, W, LD2>>;
|
||||
|
||||
REQUIRE_FALSE(pfor::rwControl<Tags0>);
|
||||
REQUIRE(pfor::rwControl<Tags1>);
|
||||
REQUIRE_FALSE(pfor::rwControl<Tags2>);
|
||||
}
|
||||
}
|
||||
}
|
6
tests/main.cpp
Normal file
6
tests/main.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <pfor/pfor.h>
|
||||
|
||||
std::size_t pfor::ParallelForParameters::nThreads{2};
|
37
tests/mp/meta.cpp
Normal file
37
tests/mp/meta.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <catch.hpp>
|
||||
#include "../common.h"
|
||||
|
||||
#include <pfor/mp/meta.h>
|
||||
|
||||
template<typename T>
|
||||
struct Sizeof {
|
||||
static constexpr std::size_t value = sizeof(T);
|
||||
};
|
||||
|
||||
TEST_CASE("Meta") {
|
||||
SECTION("If") {
|
||||
TEST(REQUIRE, is_same_v<pfor::If<false, char, int>, int>);
|
||||
TEST(REQUIRE, is_same_v<pfor::If<true, char, int>, char>);
|
||||
}
|
||||
|
||||
SECTION("accumulate") {
|
||||
using E = pfor::Pack<>;
|
||||
using T = pfor::Pack<char, int, float>;
|
||||
|
||||
std::size_t esize = pfor::accumulate<Sizeof, E>(0, std::plus<std::size_t>{});
|
||||
std::size_t tsize = pfor::accumulate<Sizeof, T>(1, std::multiplies<std::size_t>{});
|
||||
|
||||
REQUIRE(esize == 0);
|
||||
REQUIRE(tsize == sizeof(char)*sizeof(int)*sizeof(float));
|
||||
}
|
||||
|
||||
SECTION("GCD") {
|
||||
pfor::IntToType<pfor::gcd(1, 0)> a; // ensure gcd can be computed at compile-time
|
||||
|
||||
REQUIRE(pfor::gcd(5, 0) == 5);
|
||||
REQUIRE(pfor::gcd(9, 0) == 9);
|
||||
REQUIRE(pfor::gcd(-21, 9) == 3);
|
||||
REQUIRE(pfor::gcd(2*3*7*11*17, 11*19*23) == 11);
|
||||
REQUIRE(pfor::gcd(2*3*7*11*17*23, -11*19*23) == 11*23);
|
||||
}
|
||||
}
|
150
tests/mp/pack.cpp
Normal file
150
tests/mp/pack.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include <catch.hpp>
|
||||
#include "../common.h"
|
||||
|
||||
#include <pfor/mp/meta.h>
|
||||
#include <pfor/mp/pack.h>
|
||||
|
||||
template<typename, typename> struct Comparator;
|
||||
template<std::size_t A, std::size_t B>
|
||||
struct Comparator<pfor::UIntToType<A>, pfor::UIntToType<B>> {
|
||||
static constexpr bool value = A < B;
|
||||
};
|
||||
|
||||
template<typename T, std::size_t I>
|
||||
using TSBefore = pfor::impl::PackSortBefore<Comparator, T, pfor::UIntToType<I>>;
|
||||
|
||||
template<typename T, std::size_t I>
|
||||
using TSAfter = pfor::impl::PackSortAfter<Comparator, T, pfor::UIntToType<I>>;
|
||||
|
||||
template<typename T, std::size_t I>
|
||||
using TSInsert = pfor::PackSortInsert<Comparator, T, pfor::UIntToType<I>>;
|
||||
|
||||
template<typename T>
|
||||
using TSort = pfor::PackSort<Comparator, T>;
|
||||
|
||||
TEST_CASE("Pack") {
|
||||
using T1 = pfor::Pack<>;
|
||||
using T2 = pfor::Pack<char>;
|
||||
using T3 = pfor::Pack<char, char>;
|
||||
using T4 = pfor::Pack<char, char, int>;
|
||||
using T5 = pfor::Pack<char, int, char, float, int, char>;
|
||||
using U3 = pfor::Pack<int, char>;
|
||||
using U4 = pfor::Pack<char, int, char>;
|
||||
using U5 = pfor::Pack<char, char, int, char>;
|
||||
|
||||
using M0 = pfor::Pack<>;
|
||||
using M1 = pfor::Pack<char>;
|
||||
using M2 = pfor::Pack<char, char, char>;
|
||||
using M3 = pfor::Pack<char, int, char>;
|
||||
using M4 = pfor::Pack<char, int, char, char, char, char, int, char>;
|
||||
|
||||
SECTION("PackGet") {
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T2, 0>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T3, 0>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T3, 1>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T4, 0>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T4, 1>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T4, 2>, int>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 0>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 1>, int>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 2>, char>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 3>, float>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 4>, int>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackGet<T5, 5>, char>);
|
||||
}
|
||||
|
||||
SECTION("PackAppend") {
|
||||
TEST(REQUIRE, is_same_v<pfor::PackAppend<T1, char>, T2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackAppend<T2, char>, T3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackAppend<T3, int>, T4>);
|
||||
}
|
||||
|
||||
SECTION("PackPrepend") {
|
||||
TEST(REQUIRE, is_same_v<pfor::PackPrepend<T2, int>, U3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackPrepend<U3, char>, U4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackPrepend<U4, char>, U5>);
|
||||
}
|
||||
|
||||
SECTION("PackRemove") {
|
||||
TEST(REQUIRE, is_same_v<pfor::PackRemove<T4, int>, T3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackRemove<M4, char>, pfor::Pack<int, int>>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackRemove<T5, double>, T5>);
|
||||
}
|
||||
|
||||
SECTION("PackContains") {
|
||||
TEST(REQUIRE_FALSE, pfor::packContains<T1, char>);
|
||||
TEST(REQUIRE, pfor::packContains<T2, char>);
|
||||
TEST(REQUIRE_FALSE, pfor::packContains<T2, int>);
|
||||
TEST(REQUIRE, pfor::packContains<T3, char>);
|
||||
TEST(REQUIRE_FALSE, pfor::packContains<T3, int>);
|
||||
TEST(REQUIRE, pfor::packContains<T4, int>);
|
||||
}
|
||||
|
||||
SECTION("PackUniq") {
|
||||
using U1 = pfor::Pack<>;
|
||||
using U2 = pfor::Pack<char>;
|
||||
using U3 = pfor::Pack<char>;
|
||||
using U4 = pfor::Pack<char, int>;
|
||||
using U5 = pfor::Pack<char, int, float>;
|
||||
|
||||
TEST(REQUIRE, is_same_v<pfor::PackUniq<T1>, U1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackUniq<T2>, U2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackUniq<T3>, U3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackUniq<T4>, U4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackUniq<T5>, U5>);
|
||||
}
|
||||
|
||||
SECTION("PackSize") {
|
||||
TEST_IF(REQUIRE, ==, 0, pfor::packSize<T1>);
|
||||
TEST_IF(REQUIRE, ==, 1, pfor::packSize<T2>);
|
||||
TEST_IF(REQUIRE, ==, 2, pfor::packSize<T3>);
|
||||
TEST_IF(REQUIRE, ==, 3, pfor::packSize<T4>);
|
||||
TEST_IF(REQUIRE, ==, 6, pfor::packSize<T5>);
|
||||
}
|
||||
|
||||
SECTION("PackMerge") {
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<>, M0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<T1>, M0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<T2>, M1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<T2, T3>, M2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<T2, U3>, M3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::PackMerge<T2, U3, T1, T2, U5>, M4>);
|
||||
}
|
||||
|
||||
SECTION("Pack sorting") {
|
||||
using IT0 = UIntsToPack<>;
|
||||
using IT1 = UIntsToPack<6, 4, 3, 8, 9, 2, 5, 3>;
|
||||
|
||||
using ST0 = IT0;
|
||||
using ST1 = UIntsToPack<2, 3, 3, 4, 5, 6, 8, 9>;
|
||||
using ST2 = UIntsToPack<2, 3, 3, 4, 5, 6, 7, 8, 9>;
|
||||
using ST3 = UIntsToPack<2, 3, 3, 4, 5, 6, 7, 7, 8, 9>;
|
||||
|
||||
using TEmpty = pfor::Pack<>;
|
||||
using BT1 = UIntsToPack<2, 3, 3, 4>;
|
||||
using AT1 = UIntsToPack<5, 6, 8, 9>;
|
||||
|
||||
SECTION("PackSortBefore") {
|
||||
TEST(REQUIRE, is_same_v<TSBefore<ST0, 5>, TEmpty>);
|
||||
TEST(REQUIRE, is_same_v<TSBefore<ST1, 2>, TEmpty>);
|
||||
TEST(REQUIRE, is_same_v<TSBefore<ST1, 5>, BT1>);
|
||||
}
|
||||
|
||||
SECTION("PackSortAfter") {
|
||||
TEST(REQUIRE, is_same_v<TSAfter<ST0, 5>, TEmpty>);
|
||||
TEST(REQUIRE, is_same_v<TSAfter<ST1, 10>, TEmpty>);
|
||||
TEST(REQUIRE, is_same_v<TSAfter<ST1, 5>, AT1>);
|
||||
}
|
||||
|
||||
SECTION("PackSortInsert") {
|
||||
TEST(REQUIRE, is_same_v<TSInsert<ST0, 7>, UIntsToPack<7>>);
|
||||
TEST(REQUIRE, is_same_v<TSInsert<ST1, 7>, ST2>);
|
||||
TEST(REQUIRE, is_same_v<TSInsert<ST2, 7>, ST3>);
|
||||
}
|
||||
|
||||
SECTION("PackSort") {
|
||||
TEST(REQUIRE, is_same_v<TSort<IT0>, ST0>);
|
||||
TEST(REQUIRE, is_same_v<TSort<IT1>, ST1>);
|
||||
}
|
||||
}
|
||||
}
|
41
tests/mp/tuple.cpp
Normal file
41
tests/mp/tuple.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <catch.hpp>
|
||||
#include "../common.h"
|
||||
|
||||
#include <pfor/mp/tuple.h>
|
||||
|
||||
TEST_CASE("mp/tuple") {
|
||||
using T0 = std::tuple<>;
|
||||
using T1 = std::tuple<class A>;
|
||||
using T2 = std::tuple<class A, class B>;
|
||||
using T3 = std::tuple<class A, class B, class C>;
|
||||
using T4 = std::tuple<class A, class B, class C, class D>;
|
||||
using T5 = std::tuple<class A, class B, class C, class D, class E>;
|
||||
using T6 = std::tuple<class A, class B, class C, class D, class E, class F>;
|
||||
|
||||
SECTION("SubTuple") {
|
||||
SECTION("empty") {
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T0, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T1, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T2, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T3, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T4, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T5, UIntsToPack<>>, T0>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T6, UIntsToPack<>>, T0>);
|
||||
}
|
||||
|
||||
SECTION("keep all") {
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T1, UIntsToPack<0>>, T1>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T2, UIntsToPack<0, 1>>, T2>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T3, UIntsToPack<0, 1, 2>>, T3>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T4, UIntsToPack<0, 1, 2, 3>>, T4>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T5, UIntsToPack<0, 1, 2, 3, 4>>, T5>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T6, UIntsToPack<0, 1, 2, 3, 4, 5>>, T6>);
|
||||
}
|
||||
|
||||
SECTION("general") {
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T6, UIntsToPack<0, 0, 0>>, std::tuple<class A, class A, class A>>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T6, UIntsToPack<2, 1, 0>>, std::tuple<class C, class B, class A>>);
|
||||
TEST(REQUIRE, is_same_v<pfor::SubTuple<T6, UIntsToPack<1, 3, 5>>, std::tuple<class B, class D, class F>>);
|
||||
}
|
||||
}
|
||||
}
|
75
tests/parallel_for.cpp
Normal file
75
tests/parallel_for.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include <catch.hpp>
|
||||
#include "common.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <pfor/pfor.h>
|
||||
|
||||
#define N 100
|
||||
|
||||
TEST_CASE("parallelFor") {
|
||||
int a[N+1], b[N], c[N], d[N], e[N], f[N];
|
||||
|
||||
std::generate_n(std::begin(a), N+1, [it=0]() mutable { return N-(it++); });
|
||||
std::generate_n(std::begin(b), N, [it=0]() mutable { return it++; });
|
||||
std::generate_n(std::begin(c), N, []{ return 250; });
|
||||
std::generate_n(std::begin(d), N, [it=0]() mutable { return it++&1; });
|
||||
std::generate_n(std::begin(e), N, [it=0]() mutable { return it++<<1; });
|
||||
std::generate_n(std::begin(f), N, []{ return 0; });
|
||||
|
||||
SECTION("multiple instructions") {
|
||||
int ca[N+1], cb[N], cc[N], cd[N], ce[N], cf[N];
|
||||
|
||||
pfor::Operand<int*, class IDa> oa{a};
|
||||
pfor::Operand<int*, class IDb> ob{b};
|
||||
pfor::Operand<int*, class IDc> oc{c};
|
||||
pfor::Operand<int*, class IDd> od{d};
|
||||
pfor::Operand<int*, class IDe> oe{e};
|
||||
pfor::Operand<int*, class IDf> of{f};
|
||||
|
||||
std::copy(std::begin(a), std::end(a), std::begin(ca));
|
||||
std::copy(std::begin(b), std::end(b), std::begin(cb));
|
||||
std::copy(std::begin(c), std::end(c), std::begin(cc));
|
||||
std::copy(std::begin(d), std::end(d), std::begin(cd));
|
||||
std::copy(std::begin(e), std::end(e), std::begin(ce));
|
||||
std::copy(std::begin(f), std::end(f), std::begin(cf));
|
||||
|
||||
SECTION("OpenMP") {
|
||||
pfor::Index i;
|
||||
pfor::parallelFor<pfor::ForLoopThread>(pfor::Range{0, N}, (
|
||||
of = oc,
|
||||
oa[i] = oa[i+_<1>],
|
||||
ob[i] = ob[i] + 2*oa[i],
|
||||
oe = oe+oe,
|
||||
oc = od
|
||||
));
|
||||
|
||||
for(std::size_t i = 0; i < N; ++i) {
|
||||
REQUIRE(f[i] == cc[i]);
|
||||
REQUIRE(a[i] == ca[i+1]);
|
||||
REQUIRE(b[i] == (cb[i] + 2*ca[i+1]));
|
||||
REQUIRE(e[i] == ce[i]+ce[i]);
|
||||
REQUIRE(c[i] == cd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Threads") {
|
||||
pfor::Index i;
|
||||
pfor::parallelFor<pfor::ForLoopThread>(pfor::Range{0, N}, (
|
||||
of = oc,
|
||||
oa[i] = oa[i+_<1>],
|
||||
ob[i] = ob[i] + 2*oa[i],
|
||||
oe = oe+oe,
|
||||
oc = od
|
||||
));
|
||||
|
||||
for(std::size_t i = 0; i < N; ++i) {
|
||||
REQUIRE(f[i] == cc[i]);
|
||||
REQUIRE(a[i] == ca[i+1]);
|
||||
REQUIRE(b[i] == (cb[i] + 2*ca[i+1]));
|
||||
REQUIRE(e[i] == ce[i]+ce[i]);
|
||||
REQUIRE(c[i] == cd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
tests/parallelizable.cpp
Normal file
80
tests/parallelizable.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <pfor/pfor.h>
|
||||
#include <pfor/traits.h>
|
||||
|
||||
template<std::size_t v>
|
||||
constexpr auto _ = pfor::ctv<v>;
|
||||
|
||||
TEST_CASE("Parallelizable") {
|
||||
using T = std::array<int, 1024>;
|
||||
|
||||
T a_;
|
||||
pfor::Operand<T, class IDT> a{a_};
|
||||
pfor::Index i;
|
||||
|
||||
auto rangeXX = pfor::Range{0,0};
|
||||
auto range01 = pfor::RangeCT<0, 1>{0};
|
||||
auto range11 = pfor::RangeCT<1, 1>{0};
|
||||
auto range02 = pfor::RangeCT<0, 2>{0};
|
||||
auto range12 = pfor::RangeCT<1, 2>{0};
|
||||
|
||||
SECTION("Linear") {
|
||||
SECTION("Basic") {
|
||||
auto e = a[_<2>*i+_<1>] = a[_<2>*i];
|
||||
|
||||
REQUIRE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE(pfor::parallelTest(range01, e));
|
||||
REQUIRE(pfor::parallelTest(range11, e));
|
||||
REQUIRE(pfor::parallelTest(range02, e));
|
||||
REQUIRE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
SECTION("Requiring step") {
|
||||
auto e = a[i+_<1>] = a[i];
|
||||
|
||||
REQUIRE_FALSE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range01, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range11, e));
|
||||
REQUIRE(pfor::parallelTest(range02, e));
|
||||
REQUIRE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
SECTION("Requiring begin and step") {
|
||||
auto e = a[_<2>*i] = a[_<3>*i+_<1>];
|
||||
|
||||
REQUIRE_FALSE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range01, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range11, e));
|
||||
REQUIRE(pfor::parallelTest(range02, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
}
|
||||
SECTION("Non linear") {
|
||||
SECTION("No properties") {
|
||||
auto e = a[i*i] = a[i*i]+1;
|
||||
|
||||
REQUIRE_FALSE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range01, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range11, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range02, e));
|
||||
REQUIRE_FALSE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
SECTION("Injective") {
|
||||
auto e = a[injective(i*i)] = a[injective(i*i)]+1;
|
||||
|
||||
REQUIRE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE(pfor::parallelTest(range01, e));
|
||||
REQUIRE(pfor::parallelTest(range11, e));
|
||||
REQUIRE(pfor::parallelTest(range02, e));
|
||||
REQUIRE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
SECTION("Strict inc inferred injective") {
|
||||
auto e = a[strictinc(i*i)] = a[strictinc(i*i)]+1;
|
||||
|
||||
REQUIRE(pfor::parallelTest(rangeXX, e));
|
||||
REQUIRE(pfor::parallelTest(range01, e));
|
||||
REQUIRE(pfor::parallelTest(range11, e));
|
||||
REQUIRE(pfor::parallelTest(range02, e));
|
||||
REQUIRE(pfor::parallelTest(range12, e));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user