Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1#ifndef _BBM_NATIVE_ARRAY_H_
2#define _BBM_NATIVE_ARRAY_H_
3
4#include <array>
5#include <ostream>
6#include <concepts>
7#include <functional>
9#include "util/reference.h"
10
11/************************************************************************/
12/*! \file array.h
13
14 \brief Core data structure for color and vecNd.
15
16*************************************************************************/
17
18namespace backbone {
19
20 // Forward Declaration
21 template<typename T, size_t N> struct array;
22
23 /*** Implementation details for array ***/
24 namespace detail {
25
26 template<typename T, size_t N>
27 struct array_impl : public std::array<T,N>
28 {
29 using base_type = std::array<T,N>;
30 public:
31
32 //! @{ \name Inherited methods from std::array
33 using base_type::operator[];
34 using base_type::begin;
35 using base_type::rbegin;
36 using base_type::end;
37 using base_type::rend;
38
39 using base_type::empty;
40 using base_type::size;
41 using typename base_type::value_type;
42 //! @}
43
44 //! \brief Copy constructor
45 template<typename U> requires std::convertible_to<U,T>
46 array_impl(const array_impl<U,N>& src) : base_type() { std::copy(src.begin(), src.end(), begin()); }
47
48 //! \brief Construct an array and set every element to 't'
49 array_impl(const T& t=0) : base_type() { std::fill(begin(), end(), t); }
50
51 //! \brief Construct an array; use std::array constructor.
52 template<typename... U> requires (sizeof...(U) > 1)
53 array_impl(U&&... u) : base_type{T(u)...} {}
54
55 //! \brief Construct from an std::array
56 array_impl(std::array<T,N>&& src) : base_type(std::forward<decltype(src)>(src)) {}
57
58 //! \brief assignment operator of array
59 template<typename U> requires requires(T a, U b) {{a=b};}
60 array_impl& operator=(const array_impl<U,N>& src)
61 {
62 std::copy(src.begin(), src.end(), begin());
63 return *this;
64 }
65
66 //! \brief assignment operator of value
67 template<typename U> requires requires(T a, U b) {{a=b};}
68 array_impl& operator=(U&& src)
69 {
70 std::fill(begin(), end(), src);
71 return *this;
72 }
73
74 //! @{ \name Basic Math Operators
75 inline auto operator-(void) const { return apply_op( std::negate<>() ); }
76 inline auto& operator++(void) { return apply_op_inplace( [](auto& r) { return ++r; }); }
77 inline auto& operator--(void) { return apply_op_inplace( [](auto& r) { return --r; }); }
78 inline auto operator++(int) { auto ret = *this; ++(*this); return ret; }
79 inline auto operator--(int) { auto ret = *this; ++(*this); return ret; }
80
81 template<typename U> inline constexpr auto operator+(U&& u) const { return apply_op( std::plus<>(), u); }
82 template<typename U> inline constexpr auto operator-(U&& u) const { return apply_op( std::minus<>(), u); }
83 template<typename U> inline constexpr auto operator*(U&& u) const { return apply_op( std::multiplies<>(), u); }
84 template<typename U> inline constexpr auto operator/(U&& u) const { return apply_op( std::divides<>(), u); }
85 template<typename U> inline constexpr auto operator%(U&& u) const { return apply_op( std::modulus<>(), u); }
86
87 template<typename U> inline constexpr auto& operator+=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r += v; }, u); }
88 template<typename U> inline constexpr auto& operator-=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r -= v; }, u); }
89 template<typename U> inline constexpr auto& operator*=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r *= v; }, u); }
90 template<typename U> inline constexpr auto& operator/=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r /= v; }, u); }
91 template<typename U> inline constexpr auto& operator%=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r %= v; }, u); }
92
93 friend inline constexpr auto operator+(const T& t, const array_impl& a) { return (a + t); }
94 friend inline constexpr auto operator-(const T& t, const array_impl& a) { return (array<T,N>(t) - a); }
95 friend inline constexpr auto operator*(const T& t, const array_impl& a) { return (a * t); }
96 friend inline constexpr auto operator/(const T& t, const array_impl& a) { return (array<T,N>(t) / a); }
97 friend inline auto operator%(const T& t, const array_impl& a) { return (array<T,N>(t) % a); }
98 // @}
99
100 //! @{ name Bit Operators
101 template<typename U> inline constexpr auto operator&(U&& u) const { return apply_op( std::bit_and<>(), u); }
102 template<typename U> inline constexpr auto operator|(U&& u) const { return apply_op( std::bit_or<>(), u); }
103 template<typename U> inline constexpr auto operator^(U&& u) const { return apply_op( std::bit_xor<>(), u); }
104 inline constexpr auto operator~(void) const { return apply_op( std::bit_not<>()); }
105
106 template<typename U> inline constexpr auto operator&=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r &= v; }, u); }
107 template<typename U> inline constexpr auto operator|=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r |= v; }, u); }
108 template<typename U> inline constexpr auto operator^=(U&& u) { return apply_op_inplace( [](auto& r, auto& v) { r ^= v; }, u); }
109
110 friend inline constexpr auto operator|(const T& t, const array_impl& a) { return (a | t); }
111 friend inline constexpr auto operator&(const T& t, const array_impl& a) { return (a & t); }
112 friend inline constexpr auto operator^(const T& t, const array_impl& a) { return (a ^ t); }
113 //! @}
114
115 //! @{ \name Logical Operators
116 template<typename U> inline constexpr auto operator&&(U&& u) const { return apply_op( std::logical_and<>(), u); }
117 template<typename U> inline constexpr auto operator||(U&& u) const { return apply_op( std::logical_or<>(), u); }
118 inline constexpr auto operator!(void) const { return apply_op( std::logical_not<>()); }
119
120 friend inline constexpr auto operator&&(const T& t, const array_impl& a) { return (a && t); }
121 friend inline constexpr auto operator||(const T& t, const array_impl& a) { return (a || t); }
122 //! @}
123
124 //! @{ \name Comparison Operators
125 template<typename U> inline constexpr auto operator<(U&& u) const { return apply_op( std::less<>(), u); }
126 template<typename U> inline constexpr auto operator<=(U&& u) const { return apply_op( std::less_equal<>(), u); }
127 template<typename U> inline constexpr auto operator>(U&& u) const { return apply_op( std::greater<>(), u); }
128 template<typename U> inline constexpr auto operator>=(U&& u) const { return apply_op( std::greater_equal<>(), u); }
129
130 friend inline constexpr auto operator<(const T& t, const array_impl& a) { return (a > t); }
131 friend inline constexpr auto operator<=(const T& t, const array_impl& a) { return (a >= t); }
132 friend inline constexpr auto operator>(const T& t, const array_impl& a) { return (a < t); }
133 friend inline constexpr auto operator>=(const T& t, const array_impl& a) { return (a <= t); }
134
135 template<typename U> friend inline constexpr bool operator==(const array_impl& t, const array_impl<U,N>& u) { auto res = t.apply_op( std::equal_to<>(), u); return std::all_of(res.begin(), res.end(), std::identity()); }
136 template<typename U> friend inline constexpr bool operator!=(const array_impl& t, const array_impl<U,N>& u) { auto res = t.apply_op( std::equal_to<>(), u); return std::none_of(res.begin(), res.end(), std::identity()); }
137 //! @}
138
139 //! \brief Print to std::ostream
140 friend std::ostream& operator<<(std::ostream& s, const array_impl<T,N>& a)
141 {
142 s << "[";
143 for(auto& v : a)
144 {
145 if(&v != a.begin()) s << ", ";
146 s << v;
147 }
148 s << "]";
149 return s;
150 }
151
152 private:
153 //! \brief Helper method for applying an operator returning a new array.
154 template<typename... U, typename OP>
155 inline auto apply_op(const OP& op, U&&... u) const
156 {
157 array< decltype( op( *begin(), (*bbm::begin(u))... ) ), N> result;
158 bbm::multirange_for([&](auto& result, auto&... arg) { result = op(arg...); }, result, *this, u...);
159 return result;
160 }
161
162 //! \brief Helper method for applying an operator in place
163 template<typename... U, typename OP>
164 inline auto& apply_op_inplace(const OP& op, U&&... u)
165 {
166 bbm::multirange_for([&](auto&... arg) { op(arg...); }, *this, u...);
167 return *this;
168 }
169 };
170 } // detail namespace
171
172
173 /**********************************************************************/
174 /*! @{ \name array type
175 **********************************************************************/
176 template<typename T, size_t N> requires (!std::is_reference_v<T>)
177 struct array<T, N> : public detail::array_impl<T, N>
178 {
179 using base_type = detail::array_impl<T,N>;
180 using base_type::base_type;
181 using base_type::operator=;
182 };
183
184 template<typename T, size_t N> requires (std::is_reference_v<T>)
185 struct array<T, N> : public detail::array_impl<bbm::reference<T>, N>
186 {
187 using base_type = detail::array_impl<bbm::reference<T>,N>;
188 using base_type::base_type;
189 using base_type::operator=;
190 };
191 //! @}
192
193 /*** Implementation details for is_array ***/
194 namespace detail {
195
196 template<typename T> struct is_array : std::false_type {};
197 template<typename T, size_t N> struct is_array<array<T,N>> : std::true_type {};
198 } // end detail namespace
199
200 /********************************************************************/
201 /*! @{ \name is_array type traits
202 ********************************************************************/
203 template<typename T>
204 using is_array = detail::is_array<std::decay_t<T>>;
205
206 template<typename T>
207 inline constexpr bool is_array_v = is_array<T>::value;
208 //! @}
209
210 /*** Implementation details for array_size ***/
211 namespace detail {
212 template<typename T> struct array_size { static constexpr size_t value = 1; };
213 template<typename T, size_t N> struct array_size<array<T,N>> { static constexpr size_t value = N; };
214 } // end detail namespace
215
216
217 /********************************************************************/
218 /*! \brief array_size type traits
219 ********************************************************************/
220 template<typename T>
221 static constexpr size_t array_size = detail::array_size< std::decay_t<T> >::value;
222
223} // end backbone namespace
224
225#endif /* _BBM_NATIVE_ARRAY_H_ */
auto & operator--(T &a)
Definition: array.h:20
auto & operator++(T &a)
Definition: array.h:14
ranged for loop over multiple containers at once
Random number generator; built on top of Drjit.
Definition: backbone.h:53
static constexpr size_t array_size
array_size type traits
Definition: array.h:221
constexpr bool is_array_v
Definition: array.h:207
detail::is_array< std::decay_t< T > > is_array
Definition: array.h:204
Definition: array.h:21
constexpr decltype(auto) b(bbm::color< T > &c)
Definition: color.h:24
constexpr decltype(auto) r(bbm::color< T > &c)
Definition: color.h:18
constexpr decltype(auto) u(bbm::vec2d< T > &v)
Definition: vec.h:37
constexpr decltype(auto) v(bbm::vec2d< T > &v)
Definition: vec.h:40
auto operator/(const vector< T > &v, const U &u)
Definition: vector_util.h:273
constexpr FLAGNAME operator+(FLAGNAME a, FLAGNAME b)
Conact two flags.
Definition: flags.h:40
constexpr FLAGNAME & operator^=(FLAGNAME &a, FLAGNAME b)
Update 'a' with a^b,.
Definition: flags.h:92
constexpr FLAGNAME & operator+=(FLAGNAME &a, FLAGNAME b)
Update 'a' with a+b.
Definition: flags.h:84
constexpr FLAGNAME operator~(FLAGNAME a)
Set/unset flag that are unset/set respectively.
Definition: flags.h:61
auto & operator*=(vector< T > &v, const U &u)
Definition: vector_util.h:267
auto operator*(const vector< T > &v, const U &u)
Definition: vector_util.h:268
constexpr FLAGNAME & operator|=(FLAGNAME &a, FLAGNAME b)
Update 'a' with a | b.
Definition: flags.h:76
auto & operator/=(vector< T > &v, const U &u)
Definition: vector_util.h:272
void multirange_for(FUNC &&func, Ts &&... containers)
ranged for loop over multiple containers at once
Definition: multirange_for.h:43
constexpr FLAGNAME operator|(FLAGNAME a, FLAGNAME b)
Concat two flags.
Definition: flags.h:33
auto & operator%=(vector< T > &v, const U &u)
Definition: vector_util.h:276
std::ostream & operator<<(std::ostream &s, const BSDF &bsdf)
Definition: bsdf_base.h:138
auto end(T &&t)
Definition: iterator_util.h:43
constexpr FLAGNAME & operator&=(FLAGNAME &a, FLAGNAME b)
Update 'a' with a & b.
Definition: flags.h:68
auto operator%(const vector< T > &v, const U &u)
Definition: vector_util.h:277
constexpr FLAGNAME operator&(FLAGNAME a, FLAGNAME b)
Get the shared flags.
Definition: flags.h:47
auto begin(T &&t)
Definition: iterator_util.h:29
auto & operator-=(vector< T > &v, const U &u)
Definition: vector_util.h:263
constexpr FLAGNAME operator^(FLAGNAME a, FLAGNAME b)
Get the flags from 'a' that are not in 'b'.
Definition: flags.h:54
auto operator-(const vector< T > &v, const U &u)
Definition: vector_util.h:264
Definition: named.h:325
Assignable reference with wrapper support for rvalues.
detail::array_impl< T, N > base_type
Definition: array.h:179
Non-persistent reference (i.e., cannot take rvalues)
Definition: reference.h:86