Belle II Software development
ntuples_full.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#pragma once
10#include <type_traits>
11#include <iostream>
12#include <vector>
13#include <iomanip>
14#include <algorithm>
15
16namespace nt {
17
18 template <auto Start, auto End, auto Inc, class F>
19 constexpr void constexpr_for(F&& f)
20 {
21 if constexpr(Start < End) {
22 f(std::integral_constant<decltype(Start), Start>());
23 constexpr_for < Start + Inc, End, Inc > (f);
24 }
25 }
26
27}
28
29
30
31
32
33
34namespace nt {
35
36 template <class _Ty>
37 using _Remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Ty>>;
38
39 template <int N, typename... Ts>
40 using NthTypeOf =
41 typename std::tuple_element<N, std::tuple<Ts...>>::type;
42
43
44
45 template <typename T1>
47 using type = T1;
48 };
49
50 template <typename T1, typename T2>
51 struct ax_type : T2 {
52 T1 v = {};
53 constexpr ax_type() {}
54 constexpr ax_type(T1 t1) : v(std::move(t1)) {}
55 constexpr ax_type operator=(T1&& t1) const { return ax_type(std::move(t1)); }
56 constexpr ax_type operator=(const T1& t1) const { return ax_type(t1); }
57
58 template <typename T_IN>
59 constexpr ax_type operator()(T_IN&& t1) const { return ax_type(std::move(static_cast<T1>(t1))); }
60
61 template <typename T_IN>
62 constexpr ax_type operator()(const T_IN& t1) const { return ax_type(static_cast<T1>(t1)); }
63 constexpr ax_type operator=(T1&& t1)
64 {
65 v = std::move(t1);
66 return *this;
67 }
68 constexpr ax_type& operator=(const T1& t1)
69 {
70 v = t1;
71 return *this;
72 }
73
74 template <typename T>
75 constexpr ax_type& operator=(const ax_type<T1, T>& t1)
76 {
77 v = t1.v;
78 return *this;
79 }
80
81 using struct_maker = T2;
82 using data_t = T1;
83
84 operator T1()
85 {
86 return v;
87 }
88
89 operator const T1() const
90 {
91 return v;
92 }
93
94 template <typename T_RHS>
95 friend constexpr bool operator<(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
96 {
97 return lhs.v < rhs.v;
98 }
99
100 template <typename T_RHS>
101 friend constexpr bool operator<=(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
102 {
103 return lhs.v <= rhs.v;
104 }
105
106 template <typename T_RHS>
107 friend constexpr bool operator==(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
108 {
109 return lhs.v == rhs.v;
110 }
111
112 template <typename T_RHS>
113 friend constexpr bool operator!=(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
114 {
115 return lhs.v != rhs.v;
116 }
117
118 template <typename T_RHS>
119 friend constexpr bool operator>=(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
120 {
121 return lhs.v >= rhs.v;
122 }
123
124 template < typename T_RHS>
125 friend constexpr bool operator>(const ax_type& lhs, const ax_type<T1, T_RHS>& rhs)
126 {
127 return lhs.v > rhs.v;
128 }
129
130
131
132
133 friend constexpr bool operator<(const ax_type& lhs, const T1& rhs)
134 {
135 return lhs.v < rhs;
136 }
137 friend constexpr bool operator<(const T1 lhs, const ax_type& rhs)
138 {
139 return lhs < rhs.v;
140 }
141
142
143 friend constexpr bool operator<=(const ax_type& lhs, const T1& rhs)
144 {
145 return lhs.v <= rhs;
146 }
147
148 friend constexpr bool operator<=(const T1& lhs, const ax_type& rhs)
149 {
150 return lhs <= rhs.v;
151 }
152
153
154 friend constexpr bool operator==(const ax_type& lhs, const T1& rhs)
155 {
156 return lhs.v == rhs;
157 }
158
159 friend constexpr bool operator==(const T1& lhs, const ax_type& rhs)
160 {
161 return lhs == rhs.v;
162 }
163
164
165 friend constexpr bool operator!=(const ax_type& lhs, const T1& rhs)
166 {
167 return lhs.v != rhs;
168 }
169
170 friend constexpr bool operator!=(const T1& lhs, const ax_type& rhs)
171 {
172 return lhs != rhs.v;
173 }
174
175
176 friend constexpr bool operator>=(const ax_type& lhs, const T1& rhs)
177 {
178 return lhs.v >= rhs;
179 }
180
181 friend constexpr bool operator>=(const T1& lhs, const ax_type& rhs)
182 {
183 return lhs >= rhs.v;
184 }
185
186
187 friend constexpr bool operator>(const ax_type& lhs, const T1& rhs)
188 {
189 return lhs.v > rhs;
190 }
191
192 friend constexpr bool operator>(const T1& lhs, const ax_type& rhs)
193 {
194 return lhs > rhs.v;
195 }
196
197
198 friend std::ostream& operator<<(std::ostream& out, const ax_type& self)
199 {
200 out << self.get_name() << " : " << self.v;
201 return out;
202 }
203
204 private:
205 using T2::operator=;
206 };
207
208 namespace comparators {
209 template <typename T1, typename... T_rest>
210 struct _nt_compare {
211
212 template <typename VECA_T, typename VECB_T>
213 static auto __isLessthen(const VECA_T& vecA, const VECB_T& vecB)
214 {
215 if constexpr(sizeof...(T_rest) > 0) {
216 if (T1::get(vecA) < T1::get(vecB)) {
217 return true;
218 } else if (T1::get(vecA) > T1::get(vecB)) {
219 return false;
220 }
221 return _nt_compare<T_rest...>::template __isLessthen(vecA, vecB);
222 } else {
223 return T1::get(vecA) < T1::get(vecB);
224 }
225 }
226
227 template <typename VECA_T, typename VECB_T>
228 static auto __isEequal(const VECA_T& vecA, const VECB_T& vecB)
229 {
230 if constexpr(sizeof...(T_rest) > 0) {
231 if (nt::_Remove_cvref_t<T1>::get(vecA) != nt::_Remove_cvref_t<T1>::get(vecB)) {
232 return false;
233 }
234 return _nt_compare<T_rest...>::template __isEequal(vecA, vecB);
235 } else {
236 return nt::_Remove_cvref_t<T1>::get(vecA) == nt::_Remove_cvref_t<T1>::get(vecB);
237 }
238 }
239 };
240
241 template <typename... T_rest>
242 auto nt_compare(T_rest&& ...)
243 {
245 }
246
247 template <typename... T_rest>
248 constexpr auto lessThan(T_rest&& ...)
249 {
250 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](const auto & lhs, const auto & rhs) {
251 return less.__isLessthen(lhs, rhs);
252 };
253 }
254
255 template <typename... T_rest>
256 constexpr auto lessThan()
257 {
258 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](const auto & lhs, const auto & rhs) {
259 return less.__isLessthen(lhs, rhs);
260 };
261 }
262
263 template <typename... T_rest>
264 constexpr auto equal(T_rest&& ...)
265 {
266 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](const auto & lhs, const auto & rhs) {
267 return less.__isEequal(lhs, rhs);
268 };
269 }
270
271 template <typename... T_rest>
272 constexpr auto equal()
273 {
274 return [less = _nt_compare<nt::_Remove_cvref_t<T_rest>...> {}](const auto & lhs, const auto & rhs) {
275 return less.__isEequal(lhs, rhs);
276 };
277 }
278 }
279
280 template <typename T1, typename T2>
281 struct ax_type2 : T1, T2 {
282
283 constexpr ax_type2() = default;
284
285 using struct_maker = T2;
286 using data_t = T1;
287 };
288
290 static constexpr int c_struct_maker = 0;
291 static constexpr int c_getter1 = 1;
292 static constexpr int c_get_name = 2;
293 };
294
295 template <typename T2>
297 using type = T2;
298
299 constexpr ax_name_container_base() = default;
300
301 template <typename T, int N>
302 struct type_wrap {
303 static constexpr int N_value = N;
304 T val;
305 using type = T;
306 };
307
308 template <typename T>
309 static constexpr auto struct_maker()
310 {
311 return decltype(std::declval<type>()(std::declval<type_wrap<T, c_struct_maker>>())) {};
312 }
313
314 template <typename Data_T>
315 using base_t = typename decltype(struct_maker<Data_T>())::type;
316
317 template <typename T>
318 static constexpr decltype(auto) get(T& t)
319 {
320 using getter1 = decltype(std::declval<type>()(std::declval<type_wrap<T&, c_getter1>>()));
321 return getter1::get(t);
322 }
323
324 template <typename T>
325 static constexpr decltype(auto) get(const T& t)
326 {
327 using getter1 = decltype(std::declval<type>()(std::declval<type_wrap<const T&, c_getter1>>()));
328 return getter1::get(t);
329 }
330 template <typename T>
331 static constexpr decltype(auto) get_value(const T& t)
332 {
333 return ax_name_container_base::get(t).v;
334 }
335
336 template <typename T>
337 static constexpr decltype(auto) get_value(T& t)
338 {
339 return ax_name_container_base::get(t).v;
340 }
341
342 static constexpr auto get_name()
343 {
344 using name_getter = decltype(std::declval<type>()(std::declval<type_wrap<int, c_get_name>>()));
345 return name_getter::get_name();
346 }
347 };
348
349 template <typename TBase>
350 struct ax_name_container : TBase {
351 constexpr ax_name_container() = default;
352
353 template <typename T>
354 constexpr decltype(auto) operator()(T&& t) const
355 {
356 return TBase::get(t);
357 }
358
359 template <typename T>
360 static constexpr decltype(auto) get_value(T& t)
361 {
362 return TBase::get(t).v;
363 }
364
365 template <typename T>
366 static constexpr decltype(auto) get_value(const T& t)
367 {
368 return TBase::get(t).v;
369 }
370
371 template <typename T>
372 constexpr auto operator=(T t) const
373 {
374
375 return ax_type<_Remove_cvref_t<T>, ax_name_container> {std::move(t)};
376 }
377 };
378
379 template <typename... Ts>
381
382 template <typename T2>
383 auto constexpr get_ax_name_container(const ax_name_container<T2>& t)
384 {
385 return ax_name_container<T2> {};
386 }
387
388 template <typename T, typename data_T>
389 struct base_maker {
390 using type = typename T::template base_t<data_T>;
391 };
392 template <typename T, typename data_T>
393 using base_maker_t = typename base_maker<T, data_T>::type;
394
395
396
397 template <typename T>
398 using ntuple_base_t = base_maker_t<_Remove_cvref_t<T>, T>;
399
400 template <typename... T>
401 struct ntuple : ntuple_base_t<T>... {
402 constexpr ntuple(const ntuple& rhs) = default;
403 constexpr ntuple& operator=(const ntuple& rhs) = default;
404 constexpr ntuple& operator=(ntuple&& rhs) = default;
405 constexpr ntuple(const T& ...t1) : ntuple_base_t<T>(t1)... {}
406
407
408 constexpr ntuple() : ntuple_base_t<T>(_Remove_cvref_t<T> {})... {}
409
410 template < typename... Ts, typename = std::enable_if_t < (sizeof...(Ts) != 1) > >
411 constexpr ntuple(Ts && ...t1) : ntuple_base_t<T>(std::forward<Ts>(t1))... {}
412
413 template <typename T2>
414 decltype(auto) operator[](const ax_name_container<T2> & t)
415 {
416 return ax_name_container<T2>::get(*this);
417 }
418
419 friend std::ostream& operator<<(std::ostream& out, const ntuple& self)
420 {
421 out << "|";
422
423 constexpr_for<0, sizeof...(T), 1>([&](auto i) {
424 using current_t = decltype(NthTypeOf<i, _Remove_cvref_t<T>...> {});
425 out << " ";
426 out << current_t::get(self);
427 out << " |";
428 });
429
430 return out;
431 }
432
433 template <typename... ARGS>
434 auto operator|(const ntuple<ARGS...>& rhs) const
435 {
436 return ntuple<T..., ARGS...>(
437 T::get(*this)...,
438 ARGS::get(rhs)...);
439 }
440
441
442 friend constexpr bool operator<(const ntuple& lhs, const ntuple& rhs)
443 {
444 constexpr auto lt = comparators::lessThan<T...>();
445 return lt(lhs, rhs);
446 }
447 inline static constexpr std::size_t __size__ = sizeof...(T);
448 };
449
450 template <typename... Ts>
451 ntuple(Ts&& ...ts) -> ntuple<_Remove_cvref_t<Ts>...>;
452
453 template <int N, typename... ARGS>
454 constexpr decltype(auto) get_nth(const nt::ntuple<ARGS...>& nt)
455 {
456 return nt::_Remove_cvref_t<nt::NthTypeOf<N, nt::_Remove_cvref_t<ARGS>...>>::get(nt);
457 }
458
459 template <int N, typename... ARGS>
460 constexpr decltype(auto) get_nth(nt::ntuple<ARGS...>& nt)
461 {
462 return nt::_Remove_cvref_t<nt::NthTypeOf<N, nt::_Remove_cvref_t<ARGS>...>>::get(nt);
463 }
464
465 // Primary template for contains_type; defaults to false
466 template <typename T, typename Ntuple>
467 struct contains_type : std::false_type {
468 };
469
470 // Specialization for ntuple
471 template <typename T, typename... ARGS>
472 struct contains_type<T, ntuple<ARGS...>> : std::disjunction<std::is_same<T, ARGS>...> {
473 };
474
475 // Helper variable template
476 template <typename T, typename Ntuple>
477 constexpr bool contains_type_v = contains_type<T, Ntuple>::value;
478
479}
480
481
482
483
484namespace nt::comparators {
485
487
488 template <typename T1, typename T2>
489 constexpr static bool __comp__(T1&& t1, T2&& t2)
490 {
491 bool ret = true;
492 constexpr_for<0, _Remove_cvref_t<T1>::__size__, 1>(
493 [&](const auto i) {
494 using N_th_T = _Remove_cvref_t<decltype(nt::get_nth<i>(t1))>;
495 if constexpr(contains_type_v<N_th_T, _Remove_cvref_t<T2>>) {
496 ret &= (N_th_T::get(t1) == N_th_T::get(t2));
497 }
498 });
499 return ret;
500 }
501
502 template <typename T1, typename T2>
503 constexpr bool operator()(T1&& t1, T2&& t2) const
504 {
505 return __comp__(std::forward<T1>(t1), std::forward<T2>(t2));
506 }
507 };
508 constexpr inline on_common_args_t on_common_args;
509}
510
511
512
513namespace nt {
514
515
516 template <typename... Ts>
517 struct dataframe : nt::base_maker_t<nt::_Remove_cvref_t<Ts>, nt::ax_type2<std::vector<Ts>, typename Ts::struct_maker>>... {
518
519 template <typename T2>
520 decltype(auto) operator[](const nt::ax_name_container<T2>& t)
521 {
522 return nt::ax_name_container<T2>::get(*this);
523 }
524
525 auto operator[](size_t i)
526 {
527 using ret_t = nt::ntuple<_Remove_cvref_t<Ts> &...>;
528 return ret_t{
529 get<Ts>()[i]...};
530 }
531
532 auto operator[](size_t i) const
533 {
534 using ret_t = nt::ntuple<const Ts& ...>;
535 return ret_t{
536 get<Ts>()[i]...};
537 }
538
539 template <typename T>
540 void push_back(const T& t)
541 {
542
543 [](auto...) {}(Ts::get(*this).emplace_back(Ts::get(t))...);
544 }
545
546 template <typename... T>
547 void emplace_back(T&& ...t)
548 {
549 static_assert(sizeof...(t) == sizeof...(Ts), "\n==============missmatched amount of arguments=================\n");
550 [](auto...) {}(T::get(*this).emplace_back(std::forward<T>(t))...);
551 }
552
553 template <typename T1>
554 decltype(auto) get() const
555 {
556 return T1::get(*this);
557 }
558
559 template <typename T1>
560 decltype(auto) get()
561 {
562 return T1::get(*this);
563 }
564
565 auto size() const
566 {
567 auto size = _Remove_cvref_t<NthTypeOf<0, Ts...>>::get(*this).size();
568 return size;
569 }
570
571 template <int N>
572 static constexpr auto get_nth_type()
573 {
574
575 return get_ax_name_container(NthTypeOf<N, _Remove_cvref_t<Ts>...> {});
576 }
577 friend std::ostream& operator<<(std::ostream& out, const dataframe& self)
578 {
579 out << "|";
580
581 constexpr_for<0, sizeof...(Ts), 1>([&](auto ntuple_index) {
582 static const auto x = self.template get_nth_type<ntuple_index>();
583 out << " ";
584 out << std::setw(5) << x.get_name();
585 out << " |";
586 });
587
588 out << "\n";
589 out << "|";
590 constexpr_for<0, sizeof...(Ts), 1>([&](auto i) {
591 out << std::setw(5) << "-------|";
592 });
593 out << "\n";
594 auto size = self.size();
595 for (int i = 0; i < size; ++i) {
596 auto current_element = self[i];
597 out << "|";
598 constexpr_for<0, sizeof...(Ts), 1>([&](auto ntuple_index) {
599 static const auto x = self.template get_nth_type<ntuple_index>();
600 out << " ";
601 out << std::setw(5) << x.get(current_element).v;
602 out << " |";
603 });
604 out << "\n";
605 }
606
607 return out;
608 }
609 };
610
611 template <typename... Ts>
612 dataframe(Ts&& ...ts) -> dataframe<_Remove_cvref_t<Ts>...>;
613
614 template <typename T>
616 };
617
618 template <typename... T>
619 struct dataframe_maker<ntuple<T...>> {
621 };
622
623 template <typename F>
624 auto fill_dataframe(int index, F&& f)
625 {
626 typename dataframe_maker<decltype(f(0))>::type ret;
627 for (int i = 0; i < index; ++i) {
628 ret.push_back(f(i));
629 }
630 return ret;
631 }
632
633 template <typename NT_T, typename FUNT>
634 void ntuple_for_each(const NT_T& ntuple, FUNT&& fun)
635 {
636 nt::constexpr_for <
637 0,
638 nt::_Remove_cvref_t<decltype(ntuple)>::__size__,
639 1 > (
640 [&](auto j) {
641 fun(
642 nt::get_nth<j>(ntuple)
643 );
644 }
645 );
646 }
647}
648
649
650namespace nt::algorithms {
651
652
653
654 struct identity_t {
655 template <typename T>
656 constexpr T&& operator()(T&& t) const
657 {
658 return t;
659 }
660 };
661 template <typename VEC, typename FUNC_T = identity_t>
662 auto sum(const VEC& vec, FUNC_T && proj = identity_t {})
663 {
664 decltype(proj(vec[0])) ret {};
665 for (auto&& e : vec) {
666 ret = ret + proj(e);
667 }
668 return ret;
669 }
670
671
672 template <typename VEC, typename FUNC_T>
673 auto add_column(const VEC& vec, FUNC_T&& func)
674 {
675 std::vector < decltype(vec[0] | func(vec[0])) > ret;
676 ret.reserve(vec.size());
677 for (const auto& e : vec) {
678 ret.push_back(e | func(e));
679 }
680 return ret;
681 }
682
683 template <typename FUNC_T>
684 auto fill_vector(size_t entries, FUNC_T&& func)
685 {
686 std::vector<decltype(func(size_t(0)))> ret;
687 ret.reserve(entries);
688 for (size_t i = 0; i < entries; ++i) {
689 ret.push_back(func(i));
690 }
691 return ret;
692 }
693
694 template <typename T0, typename T1, typename T2, typename Comparision_T, typename projecttion_t>
695 void join_vectors_r(T0& ret, const T1& t1, const T2& t2, Comparision_T comp, projecttion_t project)
696 {
697 ret.clear();
698 for (const auto& e1 : t1) {
699 for (const auto& e2 : t2) {
700 if (comp(e1, e2)) {
701 ret.push_back(project(e1, e2));
702 }
703 }
704 }
705 }
706
707 template <typename T1, typename T2, typename Comparision_T, typename projecttion_t>
708 auto join_vectors(const T1& t1, const T2& t2, Comparision_T comp, projecttion_t project)
709 {
710 std::vector<decltype(project(t1[0], t2[0]))> ret;
711 join_vectors_r(ret, t1, t2, comp, project);
712 return ret;
713 }
714
715 template <typename CONTAINER_T>
716 void sort(CONTAINER_T& container)
717 {
718 std::sort(container.begin(), container.end());
719 }
720
721 template <typename CONTAINER_T, typename COMP_T>
722 void sort(CONTAINER_T& container, COMP_T&& comp)
723 {
724 std::sort(container.begin(), container.end(), comp);
725 }
726
727 template <typename CONTAINER_T, typename OP_T>
728 auto count_if(const CONTAINER_T& container, OP_T op)
729 {
730 int i = 0;
731 for (const auto& e : container)
732 if (op(e))
733 ++i;
734 return i;
735 }
736
737 template <typename VEC_T, typename FILTER_T>
738 void filter(VEC_T& vec, FILTER_T&& f)
739 {
740 auto removeIt = std::remove_if(vec.begin(), vec.end(), [&](auto&& e) {return !f(e); });
741 vec.erase(removeIt, vec.end());
742
743 }
744
745 template <typename VEC_T, typename FILTER_T>
746 auto filter_copy(const VEC_T& vec, FILTER_T&& f)
747 {
748 VEC_T ret;
749 ret.reserve(vec.size());
750 for (const auto& e : vec) {
751 if (f(e)) {
752 ret.push_back(e);
753 }
754 }
755 return ret;
756 }
757}
758
759
760
761namespace nt::algorithms {
762
763
764
765 template <typename... T>
766 struct __group {
767 template <typename VEC_T, typename FUNC_T>
768 static auto apply_append(const std::vector<VEC_T>& vec, FUNC_T&& fun)
769 {
770 auto fun_c = [&](const auto & rng) {
771 auto tail = rng.begin();
772 return nt::ntuple<T...>(T::get(*tail)...) | fun(rng);
773 };
774 return __apply__internal__(vec, fun_c);
775 }
776
777 template <typename VEC_T, typename FUNC_T>
778 static auto apply(const std::vector<VEC_T>& vec, FUNC_T&& fun)
779 {
780 auto fun_c = [&](const auto & rng) {
781 return fun(rng);
782 };
783 return __apply__internal__(vec, fun_c);
784 }
785
786 private:
787
788 template <typename VEC_T, typename FUNC_T>
789 static auto create_empty_vector()
790 {
791 return std::vector< decltype(std::declval<FUNC_T>()(std::declval<const std::vector<VEC_T>& >())) > {};
792 }
793
794 template <typename VEC_T, typename FUNC_T>
795 static auto __apply__internal__(const std::vector<VEC_T>& vec, FUNC_T&& fun_c)
796 {
797 static constexpr auto lt = nt::comparators::lessThan<T...>();
798 static constexpr auto eq = nt::comparators::equal<T...>();
799 auto ret = create_empty_vector<VEC_T, FUNC_T>();
800
801
802
803 if (vec.empty()) {
804 return ret;
805 }
806 auto min_element = vec[0];
807 auto max_element = vec[0];
808
809 for (const auto& e : vec) {
810 if (lt(e, min_element)) {
811 min_element = e;
812 }
813
814 if (lt(max_element, e)) {
815 max_element = e;
816 }
817 }
818
819 if (eq(min_element, max_element)) {
820 ret.push_back(
821 fun_c(vec)
822 );
823 return ret;
824 }
825
826 std::vector<VEC_T> buff{};
827 buff.reserve(vec.size());
828
829
830
831 auto process = [&]() {
832 buff.clear();
833 VEC_T next_min_element{};
834 next_min_element = max_element;
835
836 for (const auto& e : vec) {
837 if (eq(min_element, e)) {
838 buff.push_back(e);
839 } else if (lt(min_element, e) && lt(e, next_min_element)) {
840 next_min_element = e;
841 }
842
843 }
844
845 min_element = next_min_element;
846
847
848 ret.push_back(fun_c(buff));
849 };
850
851 while (lt(min_element, max_element)) {
852 process();
853
854 }
855
856 process();
857
858
859 return ret;
860 }
861 };
862
863 template <typename... ARGS>
864 auto group(ARGS...)
865 {
867 }
868
869
870 template <typename T>
871 constexpr auto get_default_element(T&& t)
872 {
873 return nt::_Remove_cvref_t<decltype(t[0])> {};
874 }
875}
876
877
878
879
880
881#define ax_maker(name_) []() constexpr { \
882 auto struct_maker_template_lambda = [](auto e) constexpr { \
883 using ARG_T = decltype(e); \
884 if constexpr (e.N_value == nt::ax_name_container_base_const::c_struct_maker) \
885 { \
886 if constexpr (!std::is_reference_v<typename ARG_T::type>) \
887 { \
888 struct Zt##name_ \
889 { \
890 constexpr Zt##name_() {} \
891 constexpr Zt##name_(const decltype(e.val) &e_) : name_(e_) {} \
892 constexpr Zt##name_(decltype(e.val) &e_) : name_(e_) {} \
893 constexpr Zt##name_(decltype(e.val) &&e_) : name_(std::move(e_)) {} \
894 decltype(e.val) name_; \
895 decltype(e.val) value() const \
896 { \
897 return name_; \
898 } \
899 }; \
900 return nt::type_container<Zt##name_>{}; \
901 } \
902 else \
903 { \
904 struct Zt##name_ \
905 { \
906 Zt##name_(decltype(e.val) e_) : name_(e_) {} \
907 decltype(e.val) name_; \
908 decltype(e.val) value() const \
909 { \
910 return name_; \
911 } \
912 }; \
913 return nt::type_container<Zt##name_>{}; \
914 } \
915 } \
916 else if constexpr (e.N_value == nt::ax_name_container_base_const::c_getter1) \
917 { \
918 struct getter_t \
919 { \
920 static auto &get(decltype(e.val) x) \
921 { \
922 return x.name_; \
923 } \
924 }; \
925 return getter_t{}; \
926 } \
927 else if constexpr (e.N_value == nt::ax_name_container_base_const::c_get_name) \
928 { \
929 struct name_getter_t \
930 { \
931 static std::string get_name() \
932 { \
933 return #name_; \
934 } \
935 }; \
936 return name_getter_t{}; \
937 } \
938 }; \
939 return nt::ax_name_container< \
940 nt::ax_name_container_base<decltype(struct_maker_template_lambda)>>{}; \
941 }()
942
943#define ax_new_axis(name_, value) static constexpr inline auto name_ = (ax_maker(name_) = value)
944
945#define ax_new_axis_t(name_, value) \
946 auto __internal__##name_ = [] { return ax_maker(name_) = value; }; \
947 using name_ = decltype(__internal__##name_())
948
949
950#define nt_lessthan(...) [](){ using T = decltype( \
951 nt::comparators::nt_compare( __VA_ARGS__ ) ); \
952 static constexpr T t{}; \
953 return [&](const auto& x,const auto &y) {return t.__isLessthen(x,y);}; }()
954
955#define nt_equal(...) [](){ using T = decltype( \
956 nt::comparators::nt_compare( __VA_ARGS__ ) ); \
957 static constexpr T t{}; \
958 return [&](const auto& x,const auto &y) {return t.__isEequal(x,y);}; }()
959
960
961
962#define nt_group(...) [](){ using T = decltype( \
963 nt::algorithms::group( __VA_ARGS__ ) ); \
964 static constexpr T t{}; \
965 return t; }()
966
967
968
969// ax_new_axis(name_1231, 123);
970
971#define __nt_new_axis_core(name_) \
972 struct zt##name_ \
973 { \
974 template <typename T> \
975 struct type_wrap \
976 { \
977 constexpr type_wrap() {} \
978 template <typename T1> \
979 constexpr type_wrap(T1 &&e_) : name_(std::forward<T1>(e_)) {} \
980 T name_; \
981 }; \
982 template <typename Data_T> \
983 using base_t = type_wrap<Data_T>; \
984 static auto get_name() \
985 { \
986 return #name_; \
987 } \
988 template <typename T> \
989 static constexpr auto &get(T &t) \
990 { \
991 return t.name_; \
992 } \
993 template <typename T> \
994 static constexpr const auto &get(const T &t) \
995 { \
996 return t.name_; \
997 } \
998 }
999
1000#define __nt_new_axis(qualifier, name_, value) \
1001 namespace __nt \
1002 { \
1003 __nt_new_axis_core(name_); \
1004 } \
1005 qualifier name_ = (nt::ax_name_container<__nt::zt##name_>{} = value)
1006
1007#define nt_new_axis(name_, value) __nt_new_axis(static constexpr inline auto, name_, value)
1008#define nt_new_axis_c(name_, value) __nt_new_axis(static const inline auto, name_, value)
1009
1010#define nt_new_axis_t(name_, value) \
1011 namespace __nt \
1012 { \
1013 __nt_new_axis_core(name_); \
1014 } \
1015 using name_ = decltype(nt::ax_name_container<__nt::zt##name_>{} = value)
1016
1017#define nt_new_name(name_) \
1018 namespace __nt \
1019 { \
1020 __nt_new_axis_core(name_); \
1021 } \
1022 static constexpr inline auto name_ = nt::ax_name_container<__nt::zt##name_> {}
1023
1024#define nt_new_name_t(name_) \
1025 namespace __nt \
1026 { \
1027 __nt_new_axis_core(name_); \
1028 } \
1029 using name_ = nt::ax_name_container<__nt::zt##name_>
1030
1031
1032
1033
1034