thesis version

This commit is contained in:
2021-05-10 18:14:24 +02:00
commit caf2a692f9
281 changed files with 73182 additions and 0 deletions

View File

@ -0,0 +1,51 @@
#ifndef ALSK_ALSK_SKELETON_BONE_FARM_H
#define ALSK_ALSK_SKELETON_BONE_FARM_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename> struct Farm;
template<
typename Signature,
typename Task_, typename TaskLinks_
>
struct Farm<Signature, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
using Task = Task_;
using TaskLinks = TaskLinks_;
using Links = tmp::Pack<TaskLinks>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = tmp::Pack<>;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
Task task;
std::size_t n;
};
template<>
struct SkeletonTraits<Farm> {
static constexpr bool serial = false;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using Traverser = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
return function(parDepth, skeleton, Traverser::execute(parDepth+1, skeleton.task, function, std::forward<T>(init)));
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&& skeleton) noexcept {
return std::forward<Skeleton>(skeleton).n;
}
};
template<typename... Args, typename F>
void skeletonTraversal(Farm<Args...> const& s, F&& f) {
std::forward<F>(f)(s.task, s.n);
}
}
#endif

View File

@ -0,0 +1,60 @@
#ifndef ALSK_ALSK_SKELETON_BONE_FARMSEL_H
#define ALSK_ALSK_SKELETON_BONE_FARMSEL_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename, typename> struct FarmSel;
template<
typename Signature,
typename Task_, typename TaskLinks_,
typename Select_, typename SelectLinks_
>
struct FarmSel<Signature, tmp::Pack<Task_, TaskLinks_>, tmp::Pack<Select_, SelectLinks_>>: SkeletonBase {
using Task = Task_;
using Select = Select_;
using TaskLinks = TaskLinks_;
using SelectLinks = SelectLinks_;
using Links = tmp::Pack<TaskLinks, SelectLinks>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = tmp::Pack<>;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
Task task;
Select select;
std::size_t n;
};
template<>
struct SkeletonTraits<FarmSel> {
static constexpr bool serial = false;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
using TraverserSelect = SkeletonTraversal<typename std::decay_t<Skeleton>::Select>;
return function(parDepth, skeleton,
TraverserTask::execute(parDepth+1, skeleton.task, function, std::forward<T>(init)),
TraverserSelect::execute(parDepth, skeleton.select, function, std::forward<T>(init))
);
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&& skeleton) noexcept {
return std::forward<Skeleton>(skeleton).n;
}
};
template<typename... Args, typename F>
void skeletonTraversal(FarmSel<Args...> const& s, F f) {
f(s.task, s.n);
f(s.select, 1);
}
}
#endif

View File

@ -0,0 +1,61 @@
#ifndef ALSK_ALSK_SKELETON_BONE_ITERSEL_H
#define ALSK_ALSK_SKELETON_BONE_ITERSEL_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename, typename> struct IterSel;
template<
typename Signature,
typename Task_, typename TaskLinks_,
typename Select_, typename SelectLinks_
>
struct IterSel<Signature, tmp::Pack<Task_, TaskLinks_>, tmp::Pack<Select_, SelectLinks_>>: SkeletonBase {
using Task = Task_;
using TaskLinks = TaskLinks_;
using Select = Select_;
using SelectLinks = SelectLinks_;
using Links = tmp::Pack<TaskLinks, SelectLinks>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = tmp::Pack<>;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
Task task;
Select select;
std::size_t n;
};
template<>
struct SkeletonTraits<IterSel> {
static constexpr bool serial = true;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
using TraverserSelect = SkeletonTraversal<typename std::decay_t<Skeleton>::Select>;
return function(parDepth, skeleton,
TraverserTask::execute(parDepth, skeleton.task, function, std::forward<T>(init)),
TraverserSelect::execute(parDepth, skeleton.select, function, std::forward<T>(init))
);
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
return 1;
}
};
template<typename... Args, typename F>
void skeletonTraversal(IterSel<Args...> const& s, F f) {
f(s.task, 1);
f(s.select, 1);
}
}
#endif

View File

@ -0,0 +1,51 @@
#ifndef ALSK_ALSK_SKELETON_BONE_LOOP_H
#define ALSK_ALSK_SKELETON_BONE_LOOP_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename> struct Loop;
template<
typename Signature,
typename Task_, typename TaskLinks_
>
struct Loop<Signature, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
using Task = Task_;
using TaskLinks = TaskLinks_;
using Links = tmp::Pack<TaskLinks>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = void;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
Task task;
std::size_t n;
};
template<>
struct SkeletonTraits<Loop> {
static constexpr bool serial = true;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using Traverser = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
return function(parDepth, skeleton, Traverser::execute(parDepth, skeleton.task, function, std::forward<T>(init)));
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
return 1;
}
};
template<typename... Args, typename F>
void skeletonTraversal(Loop<Args...> const& s, F&& f) {
std::forward<F>(f)(s.task, 1);
}
}
#endif

View File

@ -0,0 +1,70 @@
#ifndef ALSK_ALSK_SKELETON_BONE_SERIAL_H
#define ALSK_ALSK_SKELETON_BONE_SERIAL_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename...> struct Serial;
template<typename Signature, typename... FunTypes, typename... LinksTypes>
struct Serial<Signature, tmp::Pack<FunTypes, LinksTypes>...>: SkeletonBase {
using Links = tmp::Pack<LinksTypes...>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = tmp::Pack<>;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
using TasksP = tmp::Pack<FunTypes...>;
using Tasks = std::tuple<FunTypes...>;
Tasks tasks;
template<std::size_t I>
constexpr auto const& task() const noexcept { return std::get<I>(tasks); }
template<std::size_t I>
constexpr auto& task() noexcept { return std::get<I>(tasks); }
};
template<>
struct SkeletonTraits<Serial> {
static constexpr bool serial = true;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
auto indices = std::make_index_sequence<std::tuple_size<decltype(skeleton.tasks)>{}>();
return _traverse(parDepth, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init), std::move(indices));
}
template<typename Skeleton, typename F, typename T, std::size_t... Is>
static constexpr decltype(auto) _traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init, std::index_sequence<Is...>) {
using Traversers = tmp::Pack<
SkeletonTraversal<std::tuple_element_t<Is, typename std::decay_t<Skeleton>::Tasks>>...
>;
return function(parDepth, skeleton, tmp::PackGet<Traversers, Is>::execute(parDepth, skeleton.template task<Is>(), function, init)...);
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
return 1;
}
};
namespace impl {
template<typename Tuple, typename F, std::size_t... indices>
void skeletonTraversalSerial(Tuple const& tasks, F f, std::index_sequence<indices...>) {
using Expander = int[];
static_cast<void>(Expander{(f(std::get<indices>(tasks), 1), 0)...});
}
}
template<typename Signature, typename... Tasks, typename F>
void skeletonTraversal(Serial<Signature, Tasks...> const& s, F&& f) {
impl::skeletonTraversalSerial(s.tasks, std::forward<F>(f), std::make_index_sequence<sizeof...(Tasks)>());
}
}
#endif

View File

@ -0,0 +1,63 @@
#ifndef ALSK_ALSK_SKELETON_BONE_WHILE_H
#define ALSK_ALSK_SKELETON_BONE_WHILE_H
#include "../bonebase.h"
namespace alsk {
template<typename, typename, typename> struct While;
template<
typename Signature,
typename Test_, typename TestLinks_,
typename Task_, typename TaskLinks_
>
struct While<Signature, tmp::Pack<Test_, TestLinks_>, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
using Test = Test_;
using TestLinks = TestLinks_;
using Task = Task_;
using TaskLinks = TaskLinks_;
using Links = tmp::Pack<TestLinks_, TaskLinks_>;
using PackP = tmp::Parameters<Signature>;
using PackR = Returns<Links>;
using PackX = tmp::Pack<>;
using Packs = arg::Placeholders<PackP, PackR, PackX>;
Test test;
Task task;
~While() noexcept {}; // -Winline
};
template<>
struct SkeletonTraits<While> {
static constexpr bool serial = true;
template<typename Skeleton, typename F, typename T>
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using TraverserTest = SkeletonTraversal<typename std::decay_t<Skeleton>::Test>;
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
return function(parDepth,
skeleton,
TraverserTest::execute(parDepth, skeleton.task, function, std::forward<T>(init)),
TraverserTask::execute(parDepth, skeleton.task, function, std::forward<T>(init))
);
}
template<typename Skeleton>
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
return 1;
}
};
template<typename... Args, typename F>
void skeletonTraversal(While<Args...> const& s, F f) {
f(s.test, 1);
f(s.task, 1);
}
}
#endif

View File

@ -0,0 +1,9 @@
#ifndef ALSK_ALSK_SKELETON_BONEBASE_H
#define ALSK_ALSK_SKELETON_BONEBASE_H
#include "skeletonbase.h"
#include "traits.h"
#include "link/args.h"
#endif

11
inc/alsk/skeleton/bones.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef ALSK_ALSK_SKELETON_BONE_H
#define ALSK_ALSK_SKELETON_BONE_H
#include "bone/farm.h"
#include "bone/farmsel.h"
#include "bone/itersel.h"
#include "bone/loop.h"
#include "bone/serial.h"
#include "bone/while.h"
#endif

View File

@ -0,0 +1,7 @@
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_H
#define ALSK_ALSK_SKELETON_LINK_ARGS_H
#include "args/placeholders.h"
#include "args/traits.h"
#endif

View File

@ -0,0 +1,32 @@
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_PLACEHOLDERS_H
#define ALSK_ALSK_SKELETON_LINK_ARGS_PLACEHOLDERS_H
#include <cstdint>
#include <tmp/pack.h>
namespace alsk {
namespace arg {
/**
* @brief argument placeholder for parameters
*/
template<std::size_t I>
struct P: std::integral_constant<std::size_t, I> {};
/**
* @brief argument placeholder for returned values
*/
template<std::size_t I>
struct R: std::integral_constant<std::size_t, I> {};
/**
* @brief argument placeholder for contextual arguments
*/
template<std::size_t I>
struct C: std::integral_constant<std::size_t, I> {};
}
}
#endif

View File

@ -0,0 +1,226 @@
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H
#define ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H
#include <functional>
#include <type_traits>
#include <utility>
#include <tmp/pack.h>
#include <tmp/traits.h>
#include "placeholders.h"
namespace alsk {
namespace arg {
/**
* @brief true if the given type is a placeholder for a parameter
*/
template<typename T> struct IsP: std::false_type {};
template<std::size_t I> struct IsP<P<I>>: std::true_type {};
template<typename T>
constexpr bool isP = IsP<T>::value;
/**
* @brief true if the given type is a placeholder for a returned value
*/
template<typename T> struct IsR: std::false_type {};
template<std::size_t I> struct IsR<R<I>>: std::true_type {};
template<typename T>
constexpr bool isR = IsR<T>::value;
/**
* @brief true if the given type is a placeholder for a contextual argument
*/
template<typename T> struct IsC: std::false_type {};
template<std::size_t I> struct IsC<C<I>>: std::true_type {};
template<typename T>
constexpr bool isC = IsC<T>::value;
/**
* @brief placeholders group
*/
template<typename P_, typename R_, typename C_>
struct Placeholders {
using P = tmp::AsPack<std::decay_t<P_>>;
using R = tmp::AsPack<std::decay_t<R_>>;
using C = tmp::AsPack<std::decay_t<C_>>;
};
}
/**
* @brief apply type mods from A to B
*/
template<typename, typename B>
struct ApplyTypeModsImpl {
using type = B; // TODO: std::decay_t<B>
};
template<typename A, typename B>
struct ApplyTypeModsImpl<A const&, B> {
using type = std::decay_t<B> const&;
};
template<typename A, typename B>
using ApplyTypeMods = typename ApplyTypeModsImpl<A, B>::type;
/**
* @brief ArgType
*/
template<typename T, typename, typename=void>
struct ArgTypeImpl {
using type = T;
};
template<typename A, typename Placeholders>
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isP<std::decay_t<A>>>> {
using type = tmp::PackGet<typename Placeholders::P, std::decay_t<A>::value>;
};
template<typename A, typename Placeholders>
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isR<std::decay_t<A>>>> {
using type = tmp::PackGet<typename Placeholders::R, std::decay_t<A>::value>;
};
template<typename A, typename Placeholders>
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isC<std::decay_t<A>>>> {
using type = tmp::PackGet<typename Placeholders::C, std::decay_t<A>::value>;
};
template<typename T, typename Placeholders>
using ArgType = typename ArgTypeImpl<T, Placeholders>::type;
/**
* @brief ArgGet
*/
template<typename, typename=void> struct ArgGet;
template<>
struct ArgGet<void> {
template<typename P, typename R, typename C>
static void get(P&&, R&&, C&&) {}
};
template<typename A>
struct ArgGet<A, std::enable_if_t<arg::isP<std::decay_t<A>>>> {
template<typename P, typename R, typename C>
static auto get(P&& p, R&&, C&&)
-> /*ApplyTypeMods<A,*/ // TODO: does not work
ArgType<A, arg::Placeholders<P, tmp::Pack<>, tmp::Pack<>>>
/*>*/ {
return std::get<std::decay_t<A>::value>(std::forward<P>(p));
}
};
template<typename A>
struct ArgGet<A, std::enable_if_t<arg::isR<std::decay_t<A>>>> {
template<typename P, typename R, typename C>
static auto get(P&&, R&& r, C&&)
-> ApplyTypeMods<A,
ArgType<A, arg::Placeholders<tmp::Pack<>, R, tmp::Pack<>>>
> {
return std::get<std::decay_t<A>::value>(std::forward<R>(r));
}
};
template<typename A>
struct ArgGet<A, std::enable_if_t<arg::isC<std::decay_t<A>>>> {
template<typename P, typename R, typename C>
static auto get(P&&, R&&, C&& x)
-> ApplyTypeMods<A,
ArgType<A, arg::Placeholders<tmp::Pack<>, tmp::Pack<>, C>>
> {
return std::get<std::decay_t<A>::value>(std::forward<C>(x));
}
};
/**
* @brief IsPlaceholder
*/
namespace impl {
template<typename A>
struct IsPlaceholder:
std::integral_constant<bool,
arg::isP<std::decay_t<A>> or arg::isR<std::decay_t<A>> or arg::isC<std::decay_t<A>>
> {};
template<typename A>
constexpr bool isPlaceholder = IsPlaceholder<A>::value;
}
/**
* @brief ArgFilter
*/
template<typename, typename = void> struct ArgFilterImpl;
template<typename Ret, typename T, typename... Ts>
struct ArgFilterImpl<Ret(T, Ts...), std::enable_if_t<impl::isPlaceholder<T>>> {
using type = tmp::FunctionCat<Ret(T), typename ArgFilterImpl<Ret(Ts...)>::type>;
};
template<typename Ret, typename T, typename... Ts>
struct ArgFilterImpl<Ret(T, Ts...), std::enable_if_t<!impl::isPlaceholder<T>>> {
using type = typename ArgFilterImpl<Ret(Ts...)>::type;
};
template<typename Ret>
struct ArgFilterImpl<Ret()> {
using type = Ret();
};
template<typename F>
using ArgFilter = typename ArgFilterImpl<F>::type;
/**
* @brief RealTypeImpl
* @param T a type to solve
* @param Placeholders the placeholders list
*/
template<typename T, typename Placeholders>
struct RealTypeImpl {
using type = ArgType<T, Placeholders>;
};
/**
* @brief RealType
* @param T a type to solve
* @param Placeholders the placeholders list
*/
template<typename T, typename Placeholders>
using RealType = typename RealTypeImpl<T, Placeholders>::type;
/**
* @brief RealSignature
*/
template<typename, typename> struct RealSignatureImpl;
template<typename Ret, typename... Ps, typename Placeholders>
struct RealSignatureImpl<Ret(Ps...), Placeholders> {
// using type = Ret(*)(typename RealType<Ps, P, R>::type...); // issue with const& parameters
using type = std::function<Ret(RealType<Ps, Placeholders>...)>;
};
template<typename T, typename Placeholders>
using RealSignature = typename RealSignatureImpl<T, Placeholders>::type;
/**
* @brief Returns
*/
template<typename> struct ReturnsImpl;
template<typename... Fs>
struct ReturnsImpl<tmp::Pack<Fs...>> {
using type = tmp::Pack<tmp::ReturnType<Fs>...>;
};
template<typename T>
using Returns = typename ReturnsImpl<T>::type;
}
#endif

View File

@ -0,0 +1,52 @@
#ifndef ALSK_ALSK_SKELETON_LINK_LINK_H
#define ALSK_ALSK_SKELETON_LINK_LINK_H
#include <tmp/pack.h>
#include "args.h"
#include "utility.h"
#include "../struct/struct.h"
namespace alsk {
/**
* @brief hold the skeleton links
*/
template<template<typename...> class T, typename F, typename... Ts>
using L = S<T, F, Ts...>;
namespace impl {
/**
* Pack of return types from links
*/
template<typename...> struct LinksToReturnTypes;
template<typename R, typename... Params, typename... Ls>
struct LinksToReturnTypes<R(Params...), Ls...> {
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
};
template<template<typename...> class Skel, typename R, typename... Params, typename... InnerLs, typename... Ls>
struct LinksToReturnTypes<alsk::L<Skel, R(Params...), InnerLs...>, Ls...> {
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
};
template<template<typename...> class Skel, std::size_t I, typename... Params, typename... InnerLs, typename... Ls>
struct LinksToReturnTypes<alsk::L<Skel, alsk::arg::R<I>(Params...), InnerLs...>, Ls...> {
using rets = typename LinksToReturnTypes<InnerLs...>::type;
using R = tmp::PackGet<rets, I>;
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
};
template<>
struct LinksToReturnTypes<> {
using type = tmp::Pack<>;
};
}
}
#endif

View File

@ -0,0 +1,27 @@
#ifndef ALSK_ALSK_SKELETON_LINK_UTILITY_H
#define ALSK_ALSK_SKELETON_LINK_UTILITY_H
#include "args.h"
namespace alsk {
template<typename> struct AutoLinkSerialImpl;
template<typename R, typename... Args>
struct AutoLinkSerialImpl<R(Args...)> {
template<typename> struct Helper;
template<std::size_t... indices>
struct Helper<std::index_sequence<indices...>> {
using in = R(alsk::arg::P<indices>...);
using out = alsk::arg::R<0>(Args...);
};
using type = Helper<decltype(std::make_index_sequence<sizeof...(Args)>())>;
};
template<typename Signature>
using AutoLinkSerial = typename AutoLinkSerialImpl<Signature>::type;
}
#endif

View File

@ -0,0 +1,50 @@
#ifndef ALSK_ALSK_SKELETON_MUSCLE_MUSCLE_H
#define ALSK_ALSK_SKELETON_MUSCLE_MUSCLE_H
#include <tmp/pack.h>
namespace alsk {
/**
* @brief hold the functionoid type and its links
*/
template<typename Type, typename Links>
using Fun = tmp::Pack<Type, Links>;
}
template<typename T, T> struct Fn;
template<typename R, typename... Ts, R(*F)(Ts...)>
struct Fn<R(*)(Ts...), F> {
using Signature = R(Ts...);
constexpr R operator()(Ts... args) { return F(args...); }
};
template<typename R, typename... Ts, R(&F)(Ts...)>
struct Fn<R(&)(Ts...), F> {
using Signature = R(Ts...);
constexpr R operator()(Ts... args) { return F(args...); }
};
#define FN(f) Fn<decltype(f)&, f>
#define FN_OVERLOAD(T, f) Fn<T, f>
/** C++17
* namespace impl {
*
* template<typename T, T> struct Fn;
*
* template<typename R, typename... Ts, R(*F)(Ts...)>
* struct Fn<R(*)(Ts...), F> {
* R operator()(Ts... args) { return F(args...); }
* };
*
* }
*
* template<auto F>
* using Fn = impl::Fn<decltype(F), F>;
*/
#endif

View File

@ -0,0 +1,11 @@
#ifndef ALSK_ALSK_SKELETON_SKELETON_H
#define ALSK_ALSK_SKELETON_SKELETON_H
#include "bones.h"
#include "utility.h"
#include "link/link.h"
#include "muscle/muscle.h"
#include "struct/struct.h"
#endif

View File

@ -0,0 +1,23 @@
#ifndef ALSK_ALSK_SKELETON_SKELETONBASE_H
#define ALSK_ALSK_SKELETON_SKELETONBASE_H
#include <cstdint>
#include "tags.h"
namespace alsk {
struct SkeletonBase {
using IsSkeleton = tag::SkeletonTag;
constexpr SkeletonBase() noexcept {}
~SkeletonBase() noexcept {}
std::size_t step = 0;
std::size_t parDepth = 0;
};
}
#endif

View File

@ -0,0 +1,17 @@
#ifndef ALSK_ALSK_SKELETON_STRUCT_STRUCT_H
#define ALSK_ALSK_SKELETON_STRUCT_STRUCT_H
namespace alsk {
/**
* @brief hold the skeleton structure
*/
template<template<typename...> class T, typename... Ts>
struct S {
template<typename... Params>
using type = T<Params...>;
};
}
#endif

12
inc/alsk/skeleton/tags.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef ALSK_ALSK_SKELETON_TAGS_H
#define ALSK_ALSK_SKELETON_TAGS_H
namespace alsk {
namespace tag {
struct SkeletonTag {};
}
}
#endif

View File

@ -0,0 +1,81 @@
#ifndef ALSK_ALSK_SKELETON_TRAITS_H
#define ALSK_ALSK_SKELETON_TRAITS_H
#include <type_traits>
#include "tags.h"
namespace alsk {
/**
* @brief true if the given type is a Skeleton
*/
template<typename T, typename = void>
struct IsSkeleton: std::false_type {};
template<typename T>
struct IsSkeleton<T, std::enable_if_t<std::is_same<typename std::decay_t<T>::IsSkeleton, tag::SkeletonTag>{}>>: std::true_type {};
template<typename T>
constexpr bool isSkeleton = IsSkeleton<T>::value;
/**
* @brief class to determine a skeleton traits
* @param serial true if the skeleton cannot be run in parallel
*/
template<template<typename...> class S>
struct SkeletonTraits {
static constexpr bool serial = true;
};
template<typename> struct SkeletonTraitsTImpl;
template<template<typename...> class S, typename... Ts>
struct SkeletonTraitsTImpl<S<Ts...>> {
using type = SkeletonTraits<S>;
};
template<typename S>
using SkeletonTraitsT = typename SkeletonTraitsTImpl<std::decay_t<S>>::type;
/**
* @brief function to dynamically traverse a skeleton tree
*
* by default, do nothing (typically muscle case)
*/
template<typename Muscle, typename F,
std::enable_if_t<not isSkeleton<std::decay_t<Muscle>>>* = nullptr
>
void skeletonTraversal(Muscle&&, F&&) {}
/**
* @brief template to specialize to implement a bone
*/
template<typename Skeleton, typename Tag, typename Executor, typename Context> struct Impl;
/**
* @brief template to specialize to define how to traverse a bone
*/
template<typename Skeleton, typename=void>
struct SkeletonTraversal;
/**
* @brief returns steps between two instances of the skeleton
*/
template<typename Skeleton, std::enable_if_t<isSkeleton<Skeleton>>* = nullptr>
constexpr std::size_t skeletonStep(Skeleton const& s) {
return s.step;
}
/**
* @brief returns 0
*/
template<typename Skeleton, std::enable_if_t<not isSkeleton<Skeleton>>* = nullptr>
constexpr std::size_t skeletonStep(Skeleton const&) {
return 0;
}
}
#endif

247
inc/alsk/skeleton/utility.h Normal file
View File

@ -0,0 +1,247 @@
#ifndef ALSK_ALSK_SKELETON_UTILITY_H
#define ALSK_ALSK_SKELETON_UTILITY_H
#include <tmp/algorithm.h>
#include <tmp/tree.h>
#include "link/link.h"
#include "struct/struct.h"
#include "muscle/muscle.h"
#include "traits.h"
namespace alsk {
namespace impl {
/**
* Build inner skeletons
*/
template<typename, typename, typename, typename, typename> struct BuildSkeletonParts;
template<
template<typename...> class Skel, typename... Ss,
typename R, typename... Params, typename... Ls,
typename PParams, typename RParams, typename XParams
>
struct BuildSkeletonParts<alsk::S<Skel, Ss...>, alsk::L<Skel, R(Params...), Ls...>, PParams, RParams, XParams> {
using Placeholders = arg::Placeholders<PParams, RParams, XParams>;
using prms = tmp::Pack<RealType<Params, Placeholders>...>;
using rets = typename LinksToReturnTypes<Ls...>::type;
using xprm = tmp::Pack<>;
using type = alsk::Fun<
Skel<
R(RealType<Params, Placeholders>...),
typename BuildSkeletonParts<Ss, Ls, prms, rets, xprm>::type...
>,
RealType<R, arg::Placeholders<tmp::Pack<>, rets, xprm>>(Params...)
>;
};
template<typename S, typename L, typename, typename, typename>
struct BuildSkeletonParts {
using type = alsk::Fun<S, L>;
};
/**
* Build outer skeleton
*/
template<typename, typename> struct BuildSkeleton;
template<template<typename...> class Skel, typename... Ss, typename R, typename... Params, typename... Ls>
struct BuildSkeleton<alsk::S<Skel, Ss...>, alsk::L<Skel, R(Params...), Ls...>> {
using rets = typename LinksToReturnTypes<Ls...>::type;
using xprm = tmp::Pack<>;
using type = Skel<
R(Params...),
typename BuildSkeletonParts<Ss, Ls, tmp::Pack<Params...>, rets, xprm>::type...
>;
};
}
/**
* Build a skeleton from its structure and its links
*/
template<typename S, typename L>
using BuildSkeletonT = typename impl::BuildSkeleton<S, L>::type;
template<template<typename...> class S, template<typename...> class L>
struct BuildSkeleton {
template<typename, typename> struct Type;
template<typename... SParams, typename... LParams>
struct Type<tmp::Pack<SParams...>, tmp::Pack<LParams...>> {
using type = BuildSkeletonT<S<SParams...>, L<LParams...>>;
};
template<typename SParams, typename LParams>
using type = typename Type<SParams, LParams>::type;
template<typename SParams, typename LParams>
using skeleton = typename Type<SParams, LParams>::type;
};
// is it possible?
// template<template<typename...> class S, template<typename...> class L>
// template<typename SParams, typename LParams>
// using type = typename BuildSkeleton<S, L>::type<SParams, LParams>;
template<template<typename...> class Skeleton, typename S, typename L = S>
struct Branch {
template<typename... Ts>
using skeleton = Skeleton<Ts...>;
using signature = S;
using links = L;
};
template<typename T, typename L>
struct Leaf {
using type = T;
using links = L;
};
/**
* TreeFromSkeleton
*/
template<typename, typename=void> struct TreeFromSkeletonImpl;
template<template<typename...> class Skeleton, typename S, typename... Ps>
struct TreeFromSkeletonImpl<Skeleton<S, Ps...>, std::enable_if_t<isSkeleton<Skeleton<S, Ps...>>>> {
using type = tmp::Tree<Branch<Skeleton, S, S>, typename TreeFromSkeletonImpl<Ps>::type...>;
};
template<template<typename...> class Skeleton, typename S, typename... Ps, typename L>
struct TreeFromSkeletonImpl<Fun<Skeleton<S, Ps...>, L>, std::enable_if_t<isSkeleton<Skeleton<S, Ps...>>>> {
using type = tmp::Tree<Branch<Skeleton, S, L>, typename TreeFromSkeletonImpl<Ps>::type...>;
};
template<typename T, typename L>
struct TreeFromSkeletonImpl<Fun<T, L>, std::enable_if_t<not isSkeleton<T>>> {
using type = tmp::Tree<Leaf<T, L>>;
};
template<typename T>
using TreeFromSkeleton = typename TreeFromSkeletonImpl<T>::type;
/**
* SkeletonFromTree
*/
template<typename> struct SkeletonFromTreeImpl;
template<template<typename...> class Skeleton, typename S, typename L, typename... Cs>
struct SkeletonFromTreeImpl<tmp::Tree<Branch<Skeleton, S, L>, Cs...>> {
using type = Skeleton<S, typename SkeletonFromTreeImpl<Cs>::fun...>;
using fun = Fun<type, L>;
};
template<typename T, typename L, typename... Cs>
struct SkeletonFromTreeImpl<tmp::Tree<Leaf<T, L>, Cs...>> {
using type = T;
using fun = Fun<type, L>;
};
template<typename T>
using SkeletonFromTree = typename SkeletonFromTreeImpl<T>::type;
/**
*
*/
template<typename> struct GetTemplate;
template<template<typename...> class TT, typename... Ps>
struct GetTemplate<TT<Ps...>> {
template<typename... As>
using tmpl = TT<As...>;
};
template<template<typename...> class Skel, typename... Skargs>
struct SkeletonTraversal<Skel<Skargs...>, std::enable_if_t<isSkeleton<Skel<Skargs...>>>> {
template<typename Skeleton, typename F, typename T>
static decltype(auto) execute(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
using Traits = SkeletonTraits<Skel>;
return Traits::traverse(parDepth, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init));
}
template<typename Skeleton, typename F, typename T>
static decltype(auto) execute(Skeleton&& skeleton, F&& function, T&& init) {
using Traits = SkeletonTraits<Skel>;
return Traits::traverse(0, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init));
}
};
template<typename S>
struct SkeletonTraversal<S, std::enable_if_t<not isSkeleton<S>>> {
template<typename Skeleton, typename F, typename T>
static T execute(std::size_t, Skeleton&&, F&&, T&& init) { return init; }
template<typename Skeleton, typename F, typename T>
static T execute(Skeleton&&, F&&, T&& init) { return init; }
};
}
namespace alsk {
/*
template<typename S>
struct SkeletonParallelHeightImpl {
template<typename> struct CheckParallelityImpl;
template<template<typename...> class Skel, typename Sign, typename Link>
struct CheckParallelityImpl<Branch<Skel, Sign, Link>> {
using type = std::integral_constant<bool, not SkeletonTraits<Skel>::serial>;
};
template<typename T, typename Link>
struct CheckParallelityImpl<Leaf<T, Link>> {
using type = std::integral_constant<bool, false>;
};
template<typename P>
using CheckParallelity = typename CheckParallelityImpl<P>::type;
template<typename P>
using CheckParallelityEach = tmp::Transform<P, CheckParallelity>;
template<typename LHS, typename RHS>
using Sum = std::integral_constant<decltype(LHS::value), LHS::value + RHS::value>;
template<typename P>
using SumEach = tmp::Accumulate<P, Sum, std::integral_constant<tmp::Depth, 0>>;
template<typename LHS, typename RHS>
using Max = std::integral_constant<decltype(LHS::value), (LHS::value>RHS::value)? LHS::value:RHS::value>;
using tree = TreeFromSkeleton<S>;
using rtlpaths = tmp::TreeAllRTLPaths<tree>;
using parallel = tmp::Transform<rtlpaths, CheckParallelityEach>;
using parallelc = tmp::Transform<parallel, SumEach>;
using result = tmp::Accumulate<parallelc, Max, std::integral_constant<tmp::Depth, 0>>;
static constexpr tmp::Depth value = result::value;
};
/*/
template<typename S>
struct SkeletonParallelHeightImpl {
template<typename, typename...> struct CalcHeightImpl;
template<template<typename...> class Skel, typename Sign, typename Link, typename... Ts>
struct CalcHeightImpl<Branch<Skel, Sign, Link>, Ts...> {
static constexpr tmp::Depth par = SkeletonTraits<Skel>::serial? 0:1;
using type = std::integral_constant<tmp::Depth, par + tmp::detail::Max<Ts::type::value...>>;
};
template<typename T, typename Link, typename... Ts>
struct CalcHeightImpl<Leaf<T, Link>, Ts...> {
using type = std::integral_constant<tmp::Depth, 0>;
};
template<typename P, typename... Ts>
using CalcHeight = typename CalcHeightImpl<P, Ts...>::type;
using CalcHeightDefault = std::integral_constant<tmp::Depth, 0>;
using tree = TreeFromSkeleton<S>;
static constexpr tmp::Depth value = tmp::TreeAccumulate<tree, CalcHeight, CalcHeightDefault>::value;
};
//*/
template<typename S>
constexpr tmp::Depth skeletonParallelHeight = SkeletonParallelHeightImpl<S>::value;
}
#endif