MADNESS 0.10.1
array_of_bools.h
Go to the documentation of this file.
1//
2// Created by Eduard Valeyev on 12/4/24.
3//
4
5#ifndef MADNESS_ARRAY_OF_BOOLS_H
6#define MADNESS_ARRAY_OF_BOOLS_H
7
8#include <cstddef>
9#include <array>
10#include <numeric>
11
12namespace madness {
13
14/// syntactic sugar for std::array<bool, N>
15
16/// reason to exist: so can apply logical operations to the entire pack of bools, e.g. `a && b`,
17/// and perform queries like `a.any()`, `a.none()`, etc.
18template <std::size_t N>
19class array_of_bools : public std::array<bool, N> {
20public:
21 using base_type = std::array<bool, N>;
22
23 const auto& as_array() const { return static_cast<const base_type&>(*this); }
24 auto& as_array() { return static_cast<base_type&>(*this); }
25
26 /// default ctor public only for `N==0`
27 template <std::size_t NN = N, typename = std::enable_if_t<NN==0>>
29
30 /// constructs an array filled with \p v
31 explicit array_of_bools(bool v) { as_array().fill(v); }
32
33 /// constructs an array filled with `{v, vs...}`
34 template <typename ... Bools, typename = std::enable_if_t<sizeof...(Bools)+1==N>>
35 explicit array_of_bools(bool v, Bools... vs) : base_type{{v, static_cast<bool>(vs)...}} {}
36
37 /// @return true if any element is true
38 bool any() const { return std::accumulate(this->begin(), this->end(), false, std::logical_or{}); }
39
40 /// @return true if no elements are true
41 bool none() const { return !any(); }
42
43 /// @return true if all elements are true
44 bool all() const { return std::accumulate(this->begin(), this->end(), false, std::logical_and{}); }
45
46 /// @return first \p C elements
47 template <std::size_t C, typename = std::enable_if_t<C <= N>>
48 array_of_bools<C> front() const {
49 array_of_bools<C> result;
50 std::copy(this->begin(), this->begin()+C, result.begin());
51 return result;
52 }
53
54 /// assigns \p a to the first \p C elements of this
55 /// @param a the array to assign to the front of this
56 /// @return reference to this object
57 template <std::size_t C, typename = std::enable_if_t<C <= N>>
58 array_of_bools& assign_front(const array_of_bools<C>& a) {
59 std::copy(a.begin(), a.end(), this->begin());
60 return *this;
61 }
62
63 /// @return array with first \p C elements obtained by logical AND between
64 /// \p a and the first \p C elements of this, the rest filled with the
65 /// remainder of this
66 template <std::size_t C, typename = std::enable_if_t<C <= N>>
67 array_of_bools and_front(const array_of_bools<C>& a) const {
68 array_of_bools result;
69 const auto it = std::transform(a.begin(), a.end(), this->begin(), result.begin(),
70 std::logical_and{});
71 std::copy(this->begin() + C, this->end(), it);
72 return result;
73 }
74
75 /// @return array with first \p C elements obtained by logical OR between
76 /// \p a and the first \p C elements of this, the rest filled with the
77 /// remainder of this
78 template <std::size_t C, typename = std::enable_if_t<C <= N>>
79 array_of_bools or_front(const array_of_bools<C>& a) const {
80 array_of_bools result;
81 const auto it = std::transform(a.begin(), a.end(), this->begin(), result.begin(),
82 std::logical_or{});
83 std::copy(this->begin() + C, this->end(), it);
84 return result;
85 }
86
87 /// @return last \p C elements
88 template <std::size_t C, typename = std::enable_if_t<C <= N>>
89 array_of_bools<C> back() const {
90 array_of_bools<C> result;
91 std::copy(this->begin() + (N - C), this->end(), result.begin());
92 return result;
93 }
94
95 /// assigns \p a to the last \p C elements of this
96 /// @param a the array to assign to the back of this
97 /// @return reference to this object
98 template <std::size_t C, typename = std::enable_if_t<C <= N>>
99 array_of_bools& assign_back(const array_of_bools<C>& a) {
100 std::copy(a.begin(), a.end(), this->begin() + (N - C));
101 return *this;
102 }
103
104 /// @return array with last \p C elements obtained by logical AND between
105 /// \p a and the last \p C elements of this, the rest filled with the
106 /// remainder of this
107 template <std::size_t C, typename = std::enable_if_t<C <= N>>
108 array_of_bools and_back(const array_of_bools<C>& a) const {
109 array_of_bools result;
110 const auto it =
111 std::copy(this->begin(), this->begin() + (N - C), result.begin());
112 std::transform(a.begin(), a.end(), this->begin() + (N - C), it,
113 std::logical_and{});
114 return result;
115 }
116
117 /// @return array with last \p C elements obtained by logical OR between
118 /// \p a and the last \p C elements of this, the rest filled with the
119 /// remainder of this
120 template <std::size_t C, typename = std::enable_if_t<C <= N>>
121 array_of_bools or_back(const array_of_bools<C>& a) const {
122 array_of_bools result;
123 const auto it =
124 std::copy(this->begin(), this->begin() + (N - C), result.begin());
125 std::transform(a.begin(), a.end(), this->begin() + (N - C), it,
126 std::logical_or{});
127 return result;
128 }
129
130 friend array_of_bools<N> operator&&(const array_of_bools<N>& a, const array_of_bools<N>& b) {
131 array_of_bools<N> result;
132 std::transform(a.begin(), a.end(), b.begin(), result.begin(), std::logical_and{});
133 return result;
134 }
135 friend array_of_bools<N> operator||(const array_of_bools<N>& a, const array_of_bools<N>& b) {
136 array_of_bools<N> result;
137 std::transform(a.begin(), a.end(), b.begin(), result.begin(), std::logical_or{});
138 return result;
139 }
140 friend array_of_bools<N> operator^(const array_of_bools<N>& a, const array_of_bools<N>& b) {
141 array_of_bools<N> result;
142 std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto b1, auto b2) {
143 return b1 ^ b2;
144 });
145 return result;
146 }
147 friend array_of_bools<N> operator!(const array_of_bools<N>& a) {
148 array_of_bools<N> result;
149 std::transform(a.begin(), a.end(), result.begin(), std::logical_not{});
150 return result;
151 }
152
153 friend array_of_bools<N> operator&&(const array_of_bools<N>& a, bool b) {
154 array_of_bools<N> result;
155 std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) {
156 return a_v && b;
157 });
158 return result;
159 }
160 friend array_of_bools<N> operator&&(bool b, const array_of_bools<N>& a) {
161 return a && b;
162 }
163 friend array_of_bools<N> operator||(const array_of_bools<N>& a, bool b) {
164 array_of_bools<N> result;
165 std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) {
166 return a_v || b;
167 });
168 return result;
169 }
170 friend array_of_bools<N> operator||(bool b, const array_of_bools<N>& a) {
171 return a || b;
172 }
173 friend array_of_bools<N> operator^(const array_of_bools<N>& a, bool b) {
174 array_of_bools<N> result;
175 std::transform(a.begin(), a.end(), result.begin(), [b](auto a_v) {
176 return a_v ^ b;
177 });
178 return result;
179 }
180 friend array_of_bools<N> operator^(bool b, const array_of_bools<N>& a) {
181 return a ^ b;
182 }
183
184private:
185 // "default" ctor for N!=0 only for internal use, need tagged dispatch
186 struct nonempty_default_ctor_tag{};
187 template <std::size_t NN = N, typename = std::enable_if_t<NN!=0>>
188 explicit array_of_bools(nonempty_default_ctor_tag = {}) {}
189
190 template <std::size_t NN>
191 friend class array_of_bools;
192};
193
194static_assert(std::is_same_v<array_of_bools<1>::value_type, bool>);
195static_assert(std::is_same_v<decltype(array_of_bools<1>{true}.data()), bool*>);
196static_assert(std::is_same_v<decltype(array_of_bools<2>{true, false}[0]), bool&>);
197static_assert(std::is_same_v<decltype(array_of_bools<0>{} && array_of_bools<0>{}), array_of_bools<0>>);
198static_assert(std::is_same_v<decltype(array_of_bools<0>{} || array_of_bools<0>{}), array_of_bools<0>>);
199static_assert(std::is_same_v<decltype(array_of_bools<0>{} ^ array_of_bools<0>{}), array_of_bools<0>>);
200static_assert(std::is_same_v<decltype(!array_of_bools<0>{}), array_of_bools<0>>);
201static_assert(std::is_same_v<decltype(array_of_bools<0>{} && true), array_of_bools<0>>);
202static_assert(std::is_same_v<decltype(true && array_of_bools<0>{}), array_of_bools<0>>);
203static_assert(std::is_same_v<decltype(array_of_bools<0>{} || true), array_of_bools<0>>);
204static_assert(std::is_same_v<decltype(true || array_of_bools<0>{}), array_of_bools<0>>);
205static_assert(std::is_same_v<decltype(array_of_bools<0>{} ^ true), array_of_bools<0>>);
206static_assert(std::is_same_v<decltype(true ^ array_of_bools<0>{}), array_of_bools<0>>);
207
208}
209
210#endif // MADNESS_ARRAY_OF_BOOLS_H
Definition test_ar.cc:170
syntactic sugar for std::array<bool, N>
Definition array_of_bools.h:19
array_of_bools(bool v, Bools... vs)
constructs an array filled with {v, vs...}
Definition array_of_bools.h:35
bool any() const
Definition array_of_bools.h:38
array_of_bools()
default ctor public only for N==0
Definition array_of_bools.h:28
std::array< bool, N > base_type
Definition array_of_bools.h:21
array_of_bools(bool v)
constructs an array filled with v
Definition array_of_bools.h:31
const auto & as_array() const
Definition array_of_bools.h:23
auto & as_array()
Definition array_of_bools.h:24
bool all() const
Definition array_of_bools.h:44
bool none() const
Definition array_of_bools.h:41
static const double v
Definition hatom_sf_dirac.cc:20
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
static const double b
Definition nonlinschro.cc:119
static const double a
Definition nonlinschro.cc:118
#define N
Definition testconv.cc:37