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