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