248 lines
7.9 KiB
C
248 lines
7.9 KiB
C
|
#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
|