Skip to content

Commit

Permalink
Initial combinator support (#271)
Browse files Browse the repository at this point in the history
* add utility for operation on function operands

* add tuple_slice utility fn

* refactor functor application to handle stack-like operands

* initial combinator support

* update tests

* fix for cuda
  • Loading branch information
alifahrri committed Mar 29, 2024
1 parent 74fbb6e commit 79e43f0
Show file tree
Hide file tree
Showing 12 changed files with 1,156 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"build": {
"args": {
"USERNAME": "${localEnv:USER}",
"BASE": "nvidia/cuda:11.8.0-devel-ubuntu20.04"
"BASE": "nvidia/cuda:11.8.0-devel-ubuntu22.04"
},
"target": "dev"
},
Expand Down
82 changes: 82 additions & 0 deletions include/nmtools/array/functional/combinator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef NMTOOLS_ARRAY_FUNCTIONAL_COMBINATOR_HPP
#define NMTOOLS_ARRAY_FUNCTIONAL_COMBINATOR_HPP

#include "nmtools/meta.hpp"
#include "nmtools/array/functional/functor.hpp"

namespace nmtools::combinator
{
using functional::functor_t, functional::fmap_t;

struct swap_t
{
template <typename lhs_t, typename rhs_t>
constexpr auto operator()(const lhs_t& lhs, const rhs_t& rhs) const
{
return pack_operands(rhs,lhs);
}
}; // swap_t

template <auto N>
struct dup_t
{
template <typename array_t>
constexpr auto operator()(const array_t& array) const
{
return meta::template_reduce<N>([&](auto init, auto){
return push_operands(array,init);
}, nmtools_tuple{});
}
}; // dup_t

template <auto N>
struct dig_t
{
template <typename...operands_t>
constexpr auto operator()(const operands_t&...operands) const
{
auto operands_pack = pack_operands(operands...);
const auto& operand_i = at(operands_pack,meta::ct_v<N>);
auto left = utility::tuple_slice(operands_pack,None,meta::ct_v<N>);
auto right = utility::tuple_slice(operands_pack,meta::ct_v<N+1>);
return cat_operands(push_operands(operand_i,left),right);
}
}; // dig_t

template <auto N>
struct bury_t
{
template <typename...operands_t>
constexpr auto operator()(const operands_t&...operands) const
{
auto operands_pack = pack_operands(operands...);
const auto& operand_i = at(operands_pack,meta::ct_v<0>);
auto left = utility::tuple_slice(operands_pack,meta::ct_v<1>,meta::ct_v<N+1>);
auto right = utility::tuple_slice(operands_pack,meta::ct_v<N+1>);
return cat_operands(left,push_operands(operand_i,right));
}
}; // bury_t

template <> struct dig_t<1> : swap_t {};
template <> struct bury_t<1> : swap_t {};

template <auto N> using dig_fmap_t = fmap_t<dig_t<N>,N+1,N+1>;
template <auto N> using dup_fmap_t = fmap_t<dup_t<N>,1,N>;
template <auto N> using bury_fmap_t = fmap_t<bury_t<N>,N+1,N+1>;

template <auto N>
constexpr inline auto bury_n = functor_t<bury_fmap_t<N>>{};
template <auto N>
constexpr inline auto dig_n = functor_t<dig_fmap_t<N>>{};
template <auto N>
constexpr inline auto dup_n = functor_t<dup_fmap_t<N>>{};

constexpr inline auto dup = dup_n<2>;
constexpr inline auto swap = functor_t(fmap_t<swap_t,2,2>{});
constexpr inline auto dig1 = dig_n<1>;
constexpr inline auto dig2 = dig_n<2>;
constexpr inline auto bury1 = bury_n<1>;
constexpr inline auto bury2 = bury_n<2>;
}

#endif // NMTOOLS_ARRAY_FUNCTIONAL_COMBINATOR_HPP
246 changes: 176 additions & 70 deletions include/nmtools/array/functional/functor.hpp

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions include/nmtools/array/fwd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#ifndef NMTOOLS_ARRAY_FWD_HPP
#define NMTOOLS_ARRAY_FWD_HPP

#include "nmtools/meta.hpp"
#include "nmtools/utility/tuple_cat.hpp"

namespace nmtools::meta
{
namespace error
{
template <typename...>
struct FWD_OPERAND_UNSUPPORTED : detail::fail_t {};
}

// the following assumes T is cvref_pointer-removed
template <typename T>
struct fwd_operand
{
static constexpr auto vtype = [](){
if constexpr (is_view_v<T>
|| is_num_v<T>
|| is_none_v<T>
|| is_constant_index_array_v<T>
|| is_constant_index_v<T>
) {
return as_value_v<const T>;
} else if constexpr (is_bounded_array_v<T>) {
return as_value_v<const T&>;
} else if constexpr (is_ndarray_v<T>) {
return as_value_v<const T*>;
} else if constexpr (is_pointer_v<T> && is_ndarray_v<remove_pointer_t<T>>) {
return as_value_v<const T>;
} else if constexpr (is_either_v<T> || is_maybe_v<T>) {
return as_value_v<const T>;
} else {
using type = error::FWD_OPERAND_UNSUPPORTED<T>;
return as_value_v<type>;
}
}();
using type = type_t<decltype(vtype)>;
}; // fwd_operand

template <typename T>
using fwd_operand_t = type_t<fwd_operand<T>>;
}

namespace nmtools
{
template <typename T>
constexpr auto fwd_operand(const T& operand)
-> meta::fwd_operand_t<T>
{
using result_t = meta::fwd_operand_t<T>;
if constexpr (meta::is_pointer_v<result_t> && !meta::is_pointer_v<T>) {
return &operand;
} else {
return operand;
}
} // fwd_operand

template <typename...Ts>
constexpr auto pack_operands(const Ts&...ts)
{
return nmtools_tuple<meta::fwd_operand_t<Ts>...>{fwd_operand(ts)...};
}

template <typename T, template<typename...>typename tuple, typename...Ts, auto...Is>
constexpr auto push_operands(const T& t, const tuple<Ts...>& ts, meta::index_sequence<Is...>)
{
return tuple<meta::fwd_operand_t<T>,meta::fwd_operand_t<Ts>...>{fwd_operand(t),fwd_operand(nmtools::get<Is>(ts))...};
}

template <typename T, template<typename...>typename tuple, typename...Ts>
constexpr auto push_operands(const T& t, const tuple<Ts...>& ts)
{
return push_operands(t,ts,meta::make_index_sequence_v<sizeof...(Ts)>);
}

template <typename T, template<typename...>typename tuple, typename...Ts, auto...Is>
constexpr auto append_operands(const tuple<Ts...>& ts, const T& t)
{
return tuple<meta::fwd_operand_t<Ts>...,meta::fwd_operand_t<T>>{fwd_operand(nmtools::get<Is>(ts))...,fwd_operand(t)};
}

template <typename T, template<typename...>typename tuple, typename...Ts>
constexpr auto append_operands(const tuple<Ts...>& ts, const T& t)
{
return append_operands(ts,t,meta::make_index_sequence_v<sizeof...(Ts)>);
}

template <template<typename...>typename tuple, typename...Ts, typename...Us, auto...TIs, auto...UIs>
constexpr auto cat_operands(const tuple<Ts...>& ts, const tuple<Us...>& us, meta::index_sequence<TIs...>, meta::index_sequence<UIs...>)
{
using result_t = tuple<
meta::fwd_operand_t<meta::remove_cvref_pointer_t<Ts>>...
, meta::fwd_operand_t<meta::remove_cvref_pointer_t<Us>>...>;
return result_t{
fwd_operand(nmtools::get<TIs>(ts))...
, fwd_operand(nmtools::get<UIs>(us))...
};
} // cat_operands

template <template<typename...>typename tuple, typename...Ts, typename...Us>
constexpr auto cat_operands(const tuple<Ts...>& ts, const tuple<Us...>& us)
{
return cat_operands(ts,us,meta::make_index_sequence_v<sizeof...(Ts)>,meta::make_index_sequence_v<sizeof...(Us)>);
}
} // namespace nmtools

#endif // NMTOOLS_ARRAY_FWD_HPP
6 changes: 3 additions & 3 deletions include/nmtools/platform/cuda.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef NMTOOLS_PLATFOM_CUDA_HPP
#define NMTOOLS_PLATFOM_CUDA_HPP
#ifndef NMTOOLS_PLATFORM_CUDA_HPP
#define NMTOOLS_PLATFORM_CUDA_HPP

#define nmtools_func_attribute __host__ __device__

Expand All @@ -19,4 +19,4 @@
#define NMTOOLS_DISABLE_STL
#endif

#endif // NMTOOLS_PLATFOM_CUDA_HPP
#endif // NMTOOLS_PLATFORM_CUDA_HPP
50 changes: 50 additions & 0 deletions include/nmtools/utility/tuple_slice.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef NMTOOLS_UTILITY_TUPLE_SLICE_HPP
#define NMTOOLS_UTILITY_TUPLE_SLICE_HPP

#include "nmtools/meta.hpp"
#include "nmtools/utility/tuple_cat.hpp"

namespace nmtools::utility
{
template <typename start_t, typename stop_t=none_t, template<typename...>typename tuple, typename...args_t>
constexpr auto tuple_slice(const tuple<args_t...>& tp, start_t=start_t{}, stop_t=stop_t{})
{
constexpr auto N = sizeof...(args_t);
constexpr auto START = [](){
if constexpr (is_none_v<start_t>) {
return 0;
} else {
return start_t::value;
}
}();
constexpr auto STOP = [](){
if constexpr (is_none_v<stop_t>) {
return sizeof...(args_t);
} else {
constexpr auto value = stop_t::value;
if constexpr (value < 0) {
return sizeof...(args_t) + value;
} else {
return value;
}
}
}();
return meta::template_reduce<N>([&](auto init, auto index){
constexpr auto i = decltype(index)::value;
if constexpr ((i >= START) && (i<STOP)) {
auto& element = nmtools::get<i>(tp);
using element_t = decltype(element);
// TODO: proper fix
if constexpr (meta::is_bounded_array_v<element_t>) {
return tuple_append<element_t&>(init,element);
} else {
return tuple_append(init,element);
}
} else {
return init;
}
}, nmtools_tuple{});
} // tuple_slice
} // namespace nmtools::utility

#endif // NMTOOLS_UTILITY_TUPLE_SLICE_HPP
5 changes: 5 additions & 0 deletions tests/functional/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ if (NMTOOLS_FUNCTIONAL_TEST_ALL)
src/composition/reduce_maximum_subtract.cpp
src/composition/reduce_maximum_subtract_exp.cpp
src/composition/subtract_exp.cpp

src/combinator/bury.cpp
src/combinator/dig.cpp
src/combinator/swap.cpp
src/combinator/dup.cpp
)
endif()

Expand Down
Loading

0 comments on commit 79e43f0

Please sign in to comment.