18 template <auto Start, auto End, auto Inc,
class F>
19 constexpr void constexpr_for(F&& f)
21 if constexpr(Start < End) {
22 f(std::integral_constant<
decltype(Start), Start>());
23 constexpr_for < Start + Inc, End, Inc > (f);
36 using element_type = T;
37 using value_type = std::remove_cv_t<T>;
38 using size_type = std::size_t;
39 using difference_type = std::ptrdiff_t;
45 using iterator_category = std::forward_iterator_tag;
47 using difference_type = std::ptrdiff_t;
51 iterator(std::byte* ptr, size_type stride)
52 : m_ptr(ptr), m_stride(stride) {}
54 reference operator*()
const {
return *
reinterpret_cast<pointer
>(m_ptr); }
55 pointer operator->()
const {
return reinterpret_cast<pointer
>(m_ptr); }
72 return a.m_ptr == b.m_ptr;
77 return a.m_ptr != b.m_ptr;
85 span(std::byte* ptr, size_type count, size_type stride =
sizeof(T))
86 : m_ptr(ptr), m_count(count), m_stride(stride) {}
88 reference operator[](size_type idx)
const
90 return *
reinterpret_cast<pointer
>(m_ptr + idx * m_stride);
93 pointer data() const noexcept
95 return reinterpret_cast<pointer
>(m_ptr);
98 size_type size() const noexcept
103 size_type stride() const noexcept
108 iterator begin() const noexcept
110 return iterator(m_ptr, m_stride);
113 iterator end() const noexcept
115 return iterator(m_ptr + m_count * m_stride, m_stride);
126#define nt_span(container, member) nt::span<decltype(container[0].member.v)>( \
127 container.size() ? (std::byte *)&decltype(container[0].member)::get(container[0]) : nullptr, \
128 container.size(), sizeof(decltype(container[0])))
130#define nt_span_t(container, member) nt::span<decltype(container[0].member)>( \
131 container.size() ? (std::byte *)&decltype(container[0].member)::get(container[0]) : nullptr, \
132 container.size(), sizeof(decltype(container[0])))
137 using _Remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Ty>>;
139 template <
int N,
typename... Ts>
141 typename std::tuple_element<N, std::tuple<Ts...>>::type;
143 template <
typename T1>
148 template <
typename T1,
typename T2>
152 constexpr ax_type(T1 t1) : v(std::move(t1)) {}
153 constexpr ax_type operator=(T1&& t1)
const {
return ax_type(std::move(t1)); }
154 constexpr ax_type operator=(
const T1& t1)
const {
return ax_type(t1); }
156 template <
typename T_IN>
157 constexpr ax_type operator()(T_IN&& t1)
const {
return ax_type(std::move(
static_cast<T1
>(t1))); }
159 template <
typename T_IN>
160 constexpr ax_type operator()(
const T_IN& t1)
const {
return ax_type(
static_cast<T1
>(t1)); }
161 constexpr ax_type operator=(T1&& t1)
166 constexpr ax_type& operator=(
const T1& t1)
172 template <
typename T>
179 using struct_maker = T2;
187 operator const T1()
const
192 template <
typename T_RHS>
195 return lhs.v < rhs.v;
198 template <
typename T_RHS>
201 return lhs.v <= rhs.v;
204 template <
typename T_RHS>
207 return lhs.v == rhs.v;
210 template <
typename T_RHS>
213 return lhs.v != rhs.v;
216 template <
typename T_RHS>
219 return lhs.v >= rhs.v;
222 template <
typename T_RHS>
225 return lhs.v > rhs.v;
228 friend constexpr bool operator<(
const ax_type& lhs,
const T1& rhs)
232 friend constexpr bool operator<(
const T1 lhs,
const ax_type& rhs)
237 friend constexpr bool operator<=(
const ax_type& lhs,
const T1& rhs)
242 friend constexpr bool operator<=(
const T1& lhs,
const ax_type& rhs)
247 friend constexpr bool operator==(
const ax_type& lhs,
const T1& rhs)
252 friend constexpr bool operator==(
const T1& lhs,
const ax_type& rhs)
257 friend constexpr bool operator!=(
const ax_type& lhs,
const T1& rhs)
262 friend constexpr bool operator!=(
const T1& lhs,
const ax_type& rhs)
267 friend constexpr bool operator>=(
const ax_type& lhs,
const T1& rhs)
272 friend constexpr bool operator>=(
const T1& lhs,
const ax_type& rhs)
277 friend constexpr bool operator>(
const ax_type& lhs,
const T1& rhs)
282 friend constexpr bool operator>(
const T1& lhs,
const ax_type& rhs)
287 friend std::ostream& operator<<(std::ostream& out,
const ax_type& self)
289 out << self.get_name() <<
" : " << self.v;
297 namespace comparators {
298 template <
typename T1,
typename... T_rest>
300 template <
typename VECA_T,
typename VECB_T>
301 static auto __isLessthen(
const VECA_T& vecA,
const VECB_T& vecB)
303 if constexpr(
sizeof...(T_rest) > 0) {
304 if (T1::get(vecA) < T1::get(vecB)) {
306 }
else if (T1::get(vecA) > T1::get(vecB)) {
311 return T1::get(vecA) < T1::get(vecB);
315 template <
typename VECA_T,
typename VECB_T>
316 static auto __isEequal(
const VECA_T& vecA,
const VECB_T& vecB)
318 if constexpr(
sizeof...(T_rest) > 0) {
319 if (nt::_Remove_cvref_t<T1>::get(vecA) != nt::_Remove_cvref_t<T1>::get(vecB)) {
324 return nt::_Remove_cvref_t<T1>::get(vecA) == nt::_Remove_cvref_t<T1>::get(vecB);
329 template <
typename... T_rest>
330 auto nt_compare(T_rest&& ...)
335 template <
typename... T_rest>
336 constexpr auto lessThan(T_rest&& ...)
338 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](
const auto & lhs,
const auto & rhs) {
339 return less.__isLessthen(lhs, rhs);
343 template <
typename... T_rest>
344 constexpr auto lessThan()
346 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](
const auto & lhs,
const auto & rhs) {
347 return less.__isLessthen(lhs, rhs);
351 template <
typename... T_rest>
352 constexpr auto equal(T_rest&& ...)
354 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](
const auto & lhs,
const auto & rhs) {
355 return less.__isEequal(lhs, rhs);
359 template <
typename... T_rest>
360 constexpr auto equal()
362 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](
const auto & lhs,
const auto & rhs) {
363 return less.__isEequal(lhs, rhs);
368 template <
typename T1,
typename T2>
373 using struct_maker = T2;
378 static constexpr int c_struct_maker = 0;
379 static constexpr int c_getter1 = 1;
380 static constexpr int c_get_name = 2;
383 template <
typename T2>
389 template <
typename T,
int N>
391 static constexpr int N_value = N;
396 template <
typename T>
397 static constexpr auto struct_maker()
399 return decltype(std::declval<type>()(std::declval<type_wrap<T, c_struct_maker>>())) {};
402 template <
typename Data_T>
403 using base_t =
typename decltype(struct_maker<Data_T>())::type;
405 template <
typename T>
406 static constexpr decltype(
auto) get(T& t)
408 using getter1 =
decltype(std::declval<type>()(std::declval<type_wrap<T&, c_getter1>>()));
409 return getter1::get(t);
412 template <
typename T>
413 static constexpr decltype(
auto) get(
const T& t)
415 using getter1 =
decltype(std::declval<type>()(std::declval<type_wrap<const T&, c_getter1>>()));
416 return getter1::get(t);
418 template <
typename T>
419 static constexpr decltype(
auto) get_value(
const T& t)
421 return ax_name_container_base::get(t).v;
424 template <
typename T>
425 static constexpr decltype(
auto) get_value(T& t)
427 return ax_name_container_base::get(t).v;
430 static constexpr auto get_name()
432 using name_getter =
decltype(std::declval<type>()(std::declval<type_wrap<int, c_get_name>>()));
433 return name_getter::get_name();
437 template <
typename TBase>
441 template <
typename T>
442 constexpr decltype(
auto)
operator()(T&& t)
const
444 return TBase::get(t);
447 template <
typename T>
448 static constexpr decltype(
auto) get_value(T& t)
450 return TBase::get(t).v;
453 template <
typename T>
454 static constexpr decltype(
auto) get_value(
const T& t)
456 return TBase::get(t).v;
459 template <
typename T>
460 constexpr auto operator=(T t)
const
467 template <
typename... Ts>
470 template <
typename T2>
476 template <
typename T,
typename data_T>
478 using type =
typename T::template base_t<data_T>;
480 template <
typename T,
typename data_T>
481 using base_maker_t =
typename base_maker<T, data_T>::type;
485 template <
typename T>
486 using ntuple_base_t = base_maker_t<_Remove_cvref_t<T>, T>;
488 template <
typename... T>
491 constexpr ntuple& operator=(
const ntuple& rhs) =
default;
493 constexpr ntuple(
const T& ...t1) : ntuple_base_t<T>(t1)... {}
496 constexpr ntuple() : ntuple_base_t<T>(_Remove_cvref_t<T> {})... {}
498 template <
typename... Ts,
typename = std::enable_if_t < (
sizeof...(Ts) != 1) > >
499 constexpr ntuple(Ts && ...t1) : ntuple_base_t<T>(std::forward<Ts>(t1))... {}
501 template <
typename T2>
507 friend std::ostream& operator<<(std::ostream& out,
const ntuple& self)
511 constexpr_for<0,
sizeof...(T), 1>([&](
auto i) {
512 using current_t =
decltype(NthTypeOf<i, _Remove_cvref_t<T>...> {});
514 out << current_t::get(self);
521 template <
typename... ARGS>
524 return ntuple<T..., ARGS...>(
530 friend constexpr bool operator<(
const ntuple& lhs,
const ntuple& rhs)
532 constexpr auto lt = comparators::lessThan<T...>();
535 inline static constexpr std::size_t __size__ =
sizeof...(T);
538 template <
typename... Ts>
541 template <
int N,
typename... ARGS>
544 return nt::_Remove_cvref_t<nt::NthTypeOf<N, nt::_Remove_cvref_t<ARGS>...>>::get(nt);
547 template <
int N,
typename... ARGS>
550 return nt::_Remove_cvref_t<nt::NthTypeOf<N, nt::_Remove_cvref_t<ARGS>...>>::get(nt);
554 template <
typename T,
typename Ntuple>
559 template <
typename T,
typename... ARGS>
564 template <
typename T,
typename Ntuple>
572namespace nt::comparators {
576 template <
typename T1,
typename T2>
577 constexpr static bool __comp__(T1&& t1, T2&& t2)
580 constexpr_for<0, _Remove_cvref_t<T1>::__size__, 1>(
582 using N_th_T = _Remove_cvref_t<decltype(nt::get_nth<i>(t1))>;
583 if constexpr(contains_type_v<N_th_T, _Remove_cvref_t<T2>>) {
584 ret &= (N_th_T::get(t1) == N_th_T::get(t2));
590 template <
typename T1,
typename T2>
591 constexpr bool operator()(T1&& t1, T2&& t2)
const
593 return __comp__(std::forward<T1>(t1), std::forward<T2>(t2));
604 template <
typename... Ts>
605 struct dataframe : nt::base_maker_t<nt::_Remove_cvref_t<Ts>, nt::ax_type2<std::vector<Ts>, typename Ts::struct_maker>>... {
607 template <
typename T2>
613 auto operator[](
size_t i)
620 auto operator[](
size_t i)
const
627 template <
typename T>
628 void push_back(
const T& t)
631 [](
auto...) {}(Ts::get(*this).emplace_back(Ts::get(t))...);
634 template <
typename... T>
635 void emplace_back(T&& ...t)
637 static_assert(
sizeof...(t) ==
sizeof...(Ts),
"\n==============mismatched amount of arguments=================\n");
638 [](
auto...) {}(T::get(*this).emplace_back(std::forward<T>(t))...);
641 template <
typename T1>
642 decltype(
auto) get()
const
644 return T1::get(*
this);
647 template <
typename T1>
650 return T1::get(*
this);
655 auto size = _Remove_cvref_t<NthTypeOf<0, Ts...>>::get(*this).size();
660 static constexpr auto get_nth_type()
663 return get_ax_name_container(NthTypeOf<N, _Remove_cvref_t<Ts>...> {});
665 friend std::ostream& operator<<(std::ostream& out,
const dataframe& self)
669 constexpr_for<0,
sizeof...(Ts), 1>([&](
auto ntuple_index) {
670 static const auto x = self.template get_nth_type<ntuple_index>();
672 out << std::setw(5) << x.get_name();
678 constexpr_for<0,
sizeof...(Ts), 1>([&](
auto i) {
679 out << std::setw(5) <<
"-------|";
682 auto size = self.size();
683 for (
int i = 0; i < size; ++i) {
684 auto current_element = self[i];
686 constexpr_for<0,
sizeof...(Ts), 1>([&](
auto ntuple_index) {
687 static const auto x = self.template get_nth_type<ntuple_index>();
689 out << std::setw(5) << x.get(current_element).v;
699 template <
typename... Ts>
702 template <
typename T>
706 template <
typename... T>
711 template <
typename F>
712 auto fill_dataframe(
int index, F&& f)
715 for (
int i = 0; i < index; ++i) {
721 template <
typename NT_T,
typename FUNT>
722 void ntuple_for_each(
const NT_T& ntuple, FUNT&& fun)
726 nt::_Remove_cvref_t<
decltype(ntuple)>::__size__,
730 nt::get_nth<j>(ntuple)
738namespace nt::algorithms {
743 template <
typename T>
744 constexpr T&& operator()(T&& t)
const
749 template <
typename VEC,
typename FUNC_T =
identity_t>
750 auto sum(
const VEC& vec, FUNC_T && proj =
identity_t {})
752 decltype(proj(vec[0])) ret{};
753 for (
auto&& e : vec) {
760 template <
typename VEC,
typename FUNC_T>
761 auto add_column(
const VEC& vec, FUNC_T&& func)
763 std::vector <
decltype(vec[0] | func(vec[0])) > ret;
764 ret.reserve(vec.size());
765 for (
const auto& e : vec) {
766 ret.push_back(e | func(e));
771 template <
typename FUNC_T>
772 auto fill_vector(
size_t entries, FUNC_T&& func)
774 std::vector<
decltype(func(
size_t(0)))> ret;
775 ret.reserve(entries);
776 for (
size_t i = 0; i < entries; ++i) {
777 ret.push_back(func(i));
782 template <
typename T0,
typename T1,
typename T2,
typename Comparision_T,
typename projecttion_t>
783 void join_vectors_r(T0& ret,
const T1& t1,
const T2& t2, Comparision_T comp, projecttion_t project)
786 for (
const auto& e1 : t1) {
787 for (
const auto& e2 : t2) {
789 ret.push_back(project(e1, e2));
795 template <
typename T1,
typename T2,
typename Comparision_T,
typename projecttion_t>
796 auto join_vectors(
const T1& t1,
const T2& t2, Comparision_T comp, projecttion_t project)
798 std::vector<
decltype(project(t1[0], t2[0]))> ret;
799 join_vectors_r(ret, t1, t2, comp, project);
803 template <
typename CONTAINER_T>
804 void sort(CONTAINER_T& container)
806 std::sort(container.begin(), container.end());
809 template <
typename CONTAINER_T,
typename COMP_T>
810 void sort(CONTAINER_T& container, COMP_T&& comp)
812 std::sort(container.begin(), container.end(), comp);
815 template <
typename CONTAINER_T,
typename OP_T>
816 auto count_if(
const CONTAINER_T& container, OP_T op)
819 for (
const auto& e : container)
825 template <
typename VEC_T,
typename FILTER_T>
826 void filter(VEC_T& vec, FILTER_T&& f)
828 auto removeIt = std::remove_if(vec.begin(), vec.end(), [&](
auto&& e) {return !f(e); });
829 vec.erase(removeIt, vec.end());
833 template <
typename VEC_T,
typename FILTER_T>
834 auto filter_copy(
const VEC_T& vec, FILTER_T&& f)
837 ret.reserve(vec.size());
838 for (
const auto& e : vec) {
849namespace nt::algorithms {
853 template <
typename... T>
855 template <
typename VEC_T,
typename FUNC_T>
856 static auto apply_append(
const std::vector<VEC_T>& vec, FUNC_T&& fun)
858 auto fun_c = [&](
const auto & rng) {
859 auto tail = rng.begin();
860 return nt::ntuple<T...>(T::get(*tail)...) | fun(rng);
862 return __apply__internal__(vec, fun_c);
865 template <
typename VEC_T,
typename FUNC_T>
866 static auto apply(
const std::vector<VEC_T>& vec, FUNC_T&& fun)
868 auto fun_c = [&](
const auto & rng) {
871 return __apply__internal__(vec, fun_c);
876 template <
typename VEC_T,
typename FUNC_T>
877 static auto create_empty_vector()
879 return std::vector< decltype(std::declval<FUNC_T>()(std::declval<const std::vector<VEC_T>& >())) > {};
882 template <
typename VEC_T,
typename FUNC_T>
883 static auto __apply__internal__(
const std::vector<VEC_T>& vec, FUNC_T&& fun_c)
885 static constexpr auto lt = nt::comparators::lessThan<T...>();
886 static constexpr auto eq = nt::comparators::equal<T...>();
887 auto ret = create_empty_vector<VEC_T, FUNC_T>();
894 auto min_element = vec[0];
895 auto max_element = vec[0];
897 for (
const auto& e : vec) {
898 if (lt(e, min_element)) {
902 if (lt(max_element, e)) {
907 if (eq(min_element, max_element)) {
914 std::vector<VEC_T> buff{};
915 buff.reserve(vec.size());
919 auto process = [&]() {
921 VEC_T next_min_element{};
922 next_min_element = max_element;
924 for (
const auto& e : vec) {
925 if (eq(min_element, e)) {
927 }
else if (lt(min_element, e) && lt(e, next_min_element)) {
928 next_min_element = e;
933 min_element = next_min_element;
936 ret.push_back(fun_c(buff));
939 while (lt(min_element, max_element)) {
951 template <
typename... ARGS>
958 template <
typename T>
959 constexpr auto get_default_element(T&& t)
961 return nt::_Remove_cvref_t<
decltype(t[0])> {};
969#define ax_maker(name_) []() constexpr { \
970 auto struct_maker_template_lambda = [](auto e) constexpr { \
971 using ARG_T = decltype(e); \
972 if constexpr (e.N_value == nt::ax_name_container_base_const::c_struct_maker) \
974 if constexpr (!std::is_reference_v<typename ARG_T::type>) \
978 constexpr Zt##name_() {} \
979 constexpr Zt##name_(const decltype(e.val) &e_) : name_(e_) {} \
980 constexpr Zt##name_(decltype(e.val) &e_) : name_(e_) {} \
981 constexpr Zt##name_(decltype(e.val) &&e_) : name_(std::move(e_)) {} \
982 decltype(e.val) name_; \
983 decltype(e.val) value() const \
988 return nt::type_container<Zt##name_>{}; \
994 Zt##name_(decltype(e.val) e_) : name_(e_) {} \
995 decltype(e.val) name_; \
996 decltype(e.val) value() const \
1001 return nt::type_container<Zt##name_>{}; \
1004 else if constexpr (e.N_value == nt::ax_name_container_base_const::c_getter1) \
1008 static auto &get(decltype(e.val) x) \
1013 return getter_t{}; \
1015 else if constexpr (e.N_value == nt::ax_name_container_base_const::c_get_name) \
1017 struct name_getter_t \
1019 static std::string get_name() \
1024 return name_getter_t{}; \
1027 return nt::ax_name_container< \
1028 nt::ax_name_container_base<decltype(struct_maker_template_lambda)>>{}; \
1031#define ax_new_axis(name_, value) static constexpr inline auto name_ = (ax_maker(name_) = value)
1033#define ax_new_axis_t(name_, value) \
1034 auto __internal__##name_ = [] { return ax_maker(name_) = value; }; \
1035 using name_ = decltype(__internal__##name_())
1038#define nt_lessthan(...) [](){ using T = decltype( \
1039 nt::comparators::nt_compare( __VA_ARGS__ ) ); \
1040 static constexpr T t{}; \
1041 return [&](const auto& x,const auto &y) {return t.__isLessthen(x,y);}; }()
1043#define nt_equal(...) [](){ using T = decltype( \
1044 nt::comparators::nt_compare( __VA_ARGS__ ) ); \
1045 static constexpr T t{}; \
1046 return [&](const auto& x,const auto &y) {return t.__isEequal(x,y);}; }()
1050#define nt_group(...) [](){ using T = decltype( \
1051 nt::algorithms::group( __VA_ARGS__ ) ); \
1052 static constexpr T t{}; \
1059#define __nt_new_axis_core(name_) \
1062 template <typename T> \
1065 constexpr type_wrap() {} \
1066 template <typename T1> \
1067 constexpr type_wrap(T1 &&e_) : name_(std::forward<T1>(e_)) {} \
1070 template <typename Data_T> \
1071 using base_t = type_wrap<Data_T>; \
1072 static auto get_name() \
1076 template <typename T> \
1077 static constexpr auto &get(T &t) \
1081 template <typename T> \
1082 static constexpr const auto &get(const T &t) \
1088#define __nt_new_axis(qualifier, name_, value) \
1091 __nt_new_axis_core(name_); \
1093 qualifier name_ = (nt::ax_name_container<__nt::zt##name_>{} = value)
1095#define nt_new_axis(name_, value) __nt_new_axis(static constexpr inline auto, name_, value)
1096#define nt_new_axis_c(name_, value) __nt_new_axis(static const inline auto, name_, value)
1098#define nt_new_axis_t(name_, value) \
1101 __nt_new_axis_core(name_); \
1103 using name_ = decltype(nt::ax_name_container<__nt::zt##name_>{} = value)
1105#define nt_new_name(name_) \
1108 __nt_new_axis_core(name_); \
1110 static constexpr inline auto name_ = nt::ax_name_container<__nt::zt##name_> {}
1112#define nt_new_name_t(name_) \
1115 __nt_new_axis_core(name_); \
1117 using name_ = nt::ax_name_container<__nt::zt##name_>