C++ Library Extensions 2022.12.09
To help learn modern C++ programming
cpg_std_array_operations.hpp
Go to the documentation of this file.
1/*
2 Author: Thomas Kim
3 First Edit: Dec. 03, 2021
4 Second Edit: Dec. 07, 2021
5 Third Edit: Dec. 09, 2021 - safe binary operation
6*/
7
8#ifndef _CGP_STD_ARRAY_OPERATIONS_HPP
9#define _CGP_STD_ARRAY_OPERATIONS_HPP
10
11#ifndef NOMINMAX
12#define NOMINMAX
13#endif
14
15#include "cpg_types.hpp"
16
17namespace std::inline stl_extensions
18{
19 namespace cgt = cpg::types;
20
21 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
22 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
23 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
24 (cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
25 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) ||
26 (cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
27 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) &&
28 cgt::common_std_array_c<LeftType, RightType>
29 constexpr decltype(auto) operator+(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
30 {
31 using container_t_a = std::remove_cvref_t<LeftType>;
32 using container_t_b = std::remove_cvref_t<RightType>;
33
34 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
35
36 if constexpr(std::same_as<container_t_a, container_t_b> &&
37 std::is_rvalue_reference_v<decltype(A)>)
38 {
39 for(std::size_t i{}; i < N; ++i)
40 A[i] = cgt::sbo(A[i]) + cgt::sbo(B[i]);
41
42 return std::move(A);
43 }
44 else if constexpr(std::same_as<container_t_a, container_t_b> &&
45 std::is_rvalue_reference_v<decltype(B)>)
46 {
47 for(std::size_t i{}; i < N; ++i)
48 B[i] = cgt::sbo(A[i]) + cgt::sbo(B[i]);
49
50 return std::move(B);
51 }
52 else
53 {
55
56 for(std::size_t i=0; i < N; ++i)
57 C[i] = cgt::sbo(A[i]) + cgt::sbo(B[i]);
58
59 return C;
60 }
61 }
62
63 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
64 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
65 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
66 (cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
67 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) ||
68 (cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
69 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) &&
70 cgt::common_std_array_c<LeftType, RightType>
71 constexpr decltype(auto) operator-(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
72 {
73 using container_t_a = std::remove_cvref_t<LeftType>;
74 using container_t_b = std::remove_cvref_t<RightType>;
75
76 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
77
78 if constexpr(std::same_as<container_t_a, container_t_b> &&
79 std::is_rvalue_reference_v<decltype(A)>)
80 {
81 for(std::size_t i{}; i < N; ++i)
82 A[i] = cgt::sbo(A[i]) - cgt::sbo(B[i]);
83
84 return std::move(A);
85 }
86 else if constexpr(std::same_as<container_t_a, container_t_b> &&
87 std::is_rvalue_reference_v<decltype(B)>)
88 {
89 for(std::size_t i{}; i < N; ++i)
90 B[i] = cgt::sbo(A[i]) - cgt::sbo(B[i]);
91
92 return std::move(B);
93 }
94 else
95 {
97
98 for(std::size_t i=0; i < N; ++i)
99 C[i] = cgt::sbo(A[i]) - cgt::sbo(B[i]);
100
101 return C;
102 }
103 }
104
105 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
106 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
107 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
108 (cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
109 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) ||
110 (cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
111 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) &&
112 cgt::common_std_array_c<LeftType, RightType>
113 constexpr decltype(auto) operator*(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
114 {
115 using container_t_a = std::remove_cvref_t<LeftType>;
116 using container_t_b = std::remove_cvref_t<RightType>;
117
118 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
119
120 if constexpr(std::same_as<container_t_a, container_t_b> &&
121 std::is_rvalue_reference_v<decltype(A)>)
122 {
123 for(std::size_t i{}; i < N; ++i)
124 A[i] = cgt::sbo(A[i]) * cgt::sbo(B[i]);
125
126 return std::move(A);
127 }
128 else if constexpr(std::same_as<container_t_a, container_t_b> &&
129 std::is_rvalue_reference_v<decltype(B)>)
130 {
131 for(std::size_t i{}; i < N; ++i)
132 B[i] = cgt::sbo(A[i]) * cgt::sbo(B[i]);
133
134 return std::move(B);
135 }
136 else
137 {
139
140 for(std::size_t i=0; i < N; ++i)
141 C[i] = cgt::sbo(A[i]) * cgt::sbo(B[i]);
142
143 return C;
144 }
145 }
146
147 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
148 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
149 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
150 (cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
151 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) ||
152 (cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
153 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>) &&
154 cgt::common_std_array_c<LeftType, RightType>
155 constexpr decltype(auto) operator/(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
156 {
157 using container_t_a = std::remove_cvref_t<LeftType>;
158 using container_t_b = std::remove_cvref_t<RightType>;
159
160 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
161
162 if constexpr(std::same_as<container_t_a, container_t_b> &&
163 std::is_rvalue_reference_v<decltype(A)>)
164 {
165 for(std::size_t i{}; i < N; ++i)
166 A[i] = cgt::sbo(A[i]) / cgt::sbo(B[i]);
167
168 return std::move(A);
169 }
170 else if constexpr(std::same_as<container_t_a, container_t_b> &&
171 std::is_rvalue_reference_v<decltype(B)>)
172 {
173 for(std::size_t i{}; i < N; ++i)
174 B[i] = cgt::sbo(A[i]) / cgt::sbo(B[i]);
175
176 return std::move(B);
177 }
178 else
179 {
181
182 for(std::size_t i=0; i < N; ++i)
183 C[i] = cgt::sbo(A[i]) / cgt::sbo(B[i]);
184
185 return C;
186 }
187 }
188
190 // vector cross product - operator% has high precedence
191 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
192 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
193 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
194 ( (std::tuple_size_v<std::remove_cvref_t<LeftType>> == 3) || (std::tuple_size_v<std::remove_cvref_t<LeftType>> == 4))
195 && cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>>
196 && cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>
197 && cgt::common_std_array_c<LeftType, RightType>
198 constexpr decltype(auto) operator%(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
199 {
200 using container_t_a = std::remove_cvref_t<LeftType>;
201 using container_t_b = std::remove_cvref_t<RightType>;
202
203 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
204
206
207 C[0] = cgt::sbo(A[1]) * cgt::sbo(B[2]) - cgt::sbo(B[1]) * cgt::sbo(A[2]);
208 C[1] = cgt::sbo(A[2]) * cgt::sbo(B[0]) - cgt::sbo(B[2]) * cgt::sbo(A[0]);
209 C[2] = cgt::sbo(A[0]) * cgt::sbo(B[1]) - cgt::sbo(B[0]) * cgt::sbo(A[1]);
210
211 if constexpr(std::tuple_size_v<std::remove_cvref_t<LeftType>> == 4)
212 C[3] = 1;
213
214 return C;
215 }
216
217 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
218 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
219 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
220 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
221 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
222 cgt::common_std_array_c<LeftType, RightType>
223 constexpr decltype(auto) operator%(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
224 {
225 using container_t_a = std::remove_cvref_t<LeftType>;
226 using container_t_b = std::remove_cvref_t<RightType>;
227
228 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
229
230 if constexpr(std::same_as<container_t_a, container_t_b> &&
231 std::is_rvalue_reference_v<decltype(A)>)
232 {
233 for(std::size_t i{}; i < N; ++i)
234 A[i] = A[i] % B[i];
235
236 return std::move(A);
237 }
238 else if constexpr(std::same_as<container_t_a, container_t_b> &&
239 std::is_rvalue_reference_v<decltype(B)>)
240 {
241 for(std::size_t i{}; i < N; ++i)
242 B[i] = A[i] % B[i];
243
244 return std::move(B);
245 }
246 else
247 {
249
250 for(std::size_t i=0; i < N; ++i)
251 C[i] = A[i] % B[i];
252
253 return C;
254 }
255 }
256
257 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
258 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
259 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
260 cgt::common_std_array_c<LeftType, RightType>
261 constexpr decltype(auto) operator%(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
262 {
263 using container_t_a = std::remove_cvref_t<LeftType>;
264 using container_t_b = std::remove_cvref_t<RightType>;
265
266 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
267
268 if constexpr(std::is_rvalue_reference_v<decltype(A)>)
269 {
270 for(std::size_t i{}; i < N; ++i)
271 A[i] = A[i] % B;
272
273 return std::move(A);
274 }
275 else
276 {
278
279 for(std::size_t i=0; i < N; ++i)
280 C[i] = A[i] % B;
281
282 return C;
283 }
284 }
285
286 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
287 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
288 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
289 cgt::common_std_array_c<LeftType, RightType>
290 constexpr decltype(auto) operator%(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
291 {
292 using container_t_a = std::remove_cvref_t<LeftType>;
293 using container_t_b = std::remove_cvref_t<RightType>;
294
295 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<RightType>>;
296
297 if constexpr(std::is_rvalue_reference_v<decltype(B)>)
298 {
299 for(std::size_t i{}; i < N; ++i)
300 B[i] = A % B[i];
301
302 return std::move(B);
303 }
304 else
305 {
307
308 // std::cout <<"A type: " >> A << std::endl;
309 // std::cout <<"B[0] type: " >> B[0] << std::endl;
310 // std::cout <<"C[0] type: " >> C[0] << std::endl;
311
312 for(std::size_t i=0; i < N; ++i)
313 C[i] = A % B[i];
314
315 return C;
316 }
317 }
318
320 // vector inner product - operator& has low precedence
321 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
322 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
323 std::tuple_size_v<std::remove_cvref_t<RightType>>)
324 && cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>>
325 && cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>
326 && cgt::common_std_array_c<LeftType, RightType>
327 constexpr decltype(auto) operator&(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
328 {
329 using container_t_a = std::remove_cvref_t<LeftType>;
330 using container_t_b = std::remove_cvref_t<RightType>;
331
332 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
333
335
336 using element_t = std::tuple_element_t<0, c_t>;
337
338 element_t R{};
339
340 for(std::size_t i=0; i < N; ++i)
341 R += cgt::sbo(A[i]) * cgt::sbo(B[i]);
342
343 return R;
344 }
345
346 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
347 requires (std::tuple_size_v<std::remove_cvref_t<LeftType>> ==
348 std::tuple_size_v<std::remove_cvref_t<RightType>>) &&
349 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
350 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
351 cgt::common_std_array_c<LeftType, RightType>
352 constexpr decltype(auto) operator&(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
353 {
354 using container_t_a = std::remove_cvref_t<LeftType>;
355 using container_t_b = std::remove_cvref_t<RightType>;
356
357 constexpr std::size_t N =
358 std::tuple_size_v<std::remove_cvref_t<LeftType>>;
359
361 using element_t = std::tuple_element_t<0, std::tuple_element_t<0, c_t> >;
362 using array_t = std::array<element_t, N>;
363
364 array_t C;
365
366 for(std::size_t i=0; i < N; ++i)
367 C[i] = A[i] & B[i];
368
369 return C;
370 }
371
372 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
373 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
374 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>
375 constexpr decltype(auto) operator&(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
376 {
377 using container_t_a = std::remove_cvref_t<LeftType>;
378 using a_t = std::tuple_element_t<0, std::tuple_element_t<0, container_t_a>>;
379
380 using container_t_b = std::remove_cvref_t<RightType>;
381 using b_t = std::tuple_element_t<0, container_t_b>;
382
383 constexpr std::size_t N = std::tuple_size_v<container_t_a>;
384
385 using c_t = std::array<cgt::common_signed_t<a_t, b_t>, N>; c_t C;
386
387 for(std::size_t i=0; i < N; ++i) C[i] = A[i] & B;
388
389 return C;
390 }
391
392 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
393 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
394 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>>
395 constexpr decltype(auto) operator&(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
396 {
397 using container_t_a = std::remove_cvref_t<LeftType>;
398 using a_t = std::tuple_element_t<0, container_t_a>;
399
400 using container_t_b = std::remove_cvref_t<RightType>;
401 using b_t = std::tuple_element_t<0, std::tuple_element_t<0, container_t_b>>;
402
403 constexpr std::size_t N = std::tuple_size_v<container_t_b>;
404
405 using c_t = std::array<cgt::common_signed_t<a_t, b_t>, N>; c_t C;
406
407 // std::cout <<"A type: " >> A << std::endl;
408 // std::cout <<"B[0] type: " >> B[0] << std::endl;
409 // std::cout <<"C[0] type: " >> C[0] << std::endl;
410
411 for(std::size_t i=0; i < N; ++i) C[i] = A & B[i];
412
413 return C;
414 }
415
417 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
418 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
419 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
420 cgt::common_std_array_c<LeftType, RightType>
421 constexpr decltype(auto) operator+(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
422 {
423 using container_t_a = std::remove_cvref_t<LeftType>;
424 using container_t_b = std::remove_cvref_t<RightType>;
425
426 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
427
428 if constexpr(std::is_rvalue_reference_v<decltype(A)>)
429 {
430 for(std::size_t i{}; i < N; ++i)
431 A[i] = A[i] + B;
432
433 return std::move(A);
434 }
435 else
436 {
438
439 for(std::size_t i=0; i < N; ++i)
440 C[i] = A[i] + B;
441
442 return C;
443 }
444 }
445
446 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
447 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
448 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
449 cgt::common_std_array_c<LeftType, RightType>
450 constexpr decltype(auto) operator+(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
451 {
452 using container_t_a = std::remove_cvref_t<LeftType>;
453 using container_t_b = std::remove_cvref_t<RightType>;
454
455 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<RightType>>;
456
457 if constexpr(std::is_rvalue_reference_v<decltype(B)>)
458 {
459 for(std::size_t i{}; i < N; ++i)
460 B[i] = A + B[i];
461
462 return std::move(B);
463 }
464 else
465 {
467
468 for(std::size_t i=0; i < N; ++i)
469 C[i] = A + B[i];
470
471 return C;
472 }
473 }
474
476 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
477 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
478 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
479 cgt::common_std_array_c<LeftType, RightType>
480 constexpr decltype(auto) operator-(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
481 {
482 using container_t_a = std::remove_cvref_t<LeftType>;
483 using container_t_b = std::remove_cvref_t<RightType>;
484
485 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
486
487 if constexpr(std::is_rvalue_reference_v<decltype(A)>)
488 {
489 for(std::size_t i{}; i < N; ++i)
490 A[i] = A[i] - B;
491
492 return std::move(A);
493 }
494 else
495 {
497
498 for(std::size_t i=0; i < N; ++i)
499 C[i] = A[i] - B;
500
501 return C;
502 }
503 }
504
505 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
506 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
507 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
508 cgt::common_std_array_c<LeftType, RightType>
509 constexpr decltype(auto) operator-(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
510 {
511 using container_t_a = std::remove_cvref_t<LeftType>;
512 using container_t_b = std::remove_cvref_t<RightType>;
513
514 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<RightType>>;
515
516 if constexpr(std::is_rvalue_reference_v<decltype(B)>)
517 {
518 for(std::size_t i{}; i < N; ++i)
519 B[i] = A - B[i];
520
521 return std::move(B);
522 }
523 else
524 {
526
527 for(std::size_t i=0; i < N; ++i)
528 C[i] = A - B[i];
529
530 return C;
531 }
532 }
533
534 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
535 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
536 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
537 cgt::common_std_array_c<LeftType, RightType>
538 constexpr decltype(auto) operator*(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
539 {
540 using container_t_a = std::remove_cvref_t<LeftType>;
541 using container_t_b = std::remove_cvref_t<RightType>;
542
543 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
544
545 if constexpr(std::is_rvalue_reference_v<decltype(A)>)
546 {
547 for(std::size_t i{}; i < N; ++i)
548 A[i] = A[i] * B;
549
550 return std::move(A);
551 }
552 else
553 {
555
556 for(std::size_t i=0; i < N; ++i)
557 C[i] = A[i] * B;
558
559 return C;
560 }
561 }
562
563 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
564 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
565 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
566 cgt::common_std_array_c<LeftType, RightType>
567 constexpr decltype(auto) operator*(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
568 {
569 using container_t_a = std::remove_cvref_t<LeftType>;
570 using container_t_b = std::remove_cvref_t<RightType>;
571
572 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<RightType>>;
573
574 if constexpr(std::is_rvalue_reference_v<decltype(B)>)
575 {
576 for(std::size_t i{}; i < N; ++i)
577 B[i] = A * B[i];
578
579 return std::move(B);
580 }
581 else
582 {
584
585 for(std::size_t i=0; i < N; ++i)
586 C[i] = A * B[i];
587
588 return C;
589 }
590 }
591
592 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
593 requires cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
594 cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
595 cgt::common_std_array_c<LeftType, RightType>
596 constexpr decltype(auto) operator/(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
597 {
598 using container_t_a = std::remove_cvref_t<LeftType>;
599 using container_t_b = std::remove_cvref_t<RightType>;
600
601 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<LeftType>>;
602
603 if constexpr(std::is_rvalue_reference_v<decltype(A)>)
604 {
605 for(std::size_t i{}; i < N; ++i)
606 A[i] = A[i] / B;
607
608 return std::move(A);
609 }
610 else
611 {
613
614 for(std::size_t i=0; i < N; ++i)
615 C[i] = A[i] / B;
616
617 return C;
618 }
619 }
620
621 template<cgt::std_array_flat_c LeftType, cgt::std_array_flat_c RightType>
622 requires cgt::numerical_c<std::tuple_element_t<0, std::remove_cvref_t<LeftType>>> &&
623 cgt::std_array_c<std::tuple_element_t<0, std::remove_cvref_t<RightType>>> &&
624 cgt::common_std_array_c<LeftType, RightType>
625 constexpr decltype(auto) operator/(LeftType&& A, RightType&& B) noexcept(!cpg::bDetectOverFlow)
626 {
627 using container_t_a = std::remove_cvref_t<LeftType>;
628 using container_t_b = std::remove_cvref_t<RightType>;
629
630 constexpr std::size_t N = std::tuple_size_v<std::remove_cvref_t<RightType>>;
631
632 if constexpr(std::is_rvalue_reference_v<decltype(B)>)
633 {
634 for(std::size_t i{}; i < N; ++i) B[i] = A / B[i];
635
636 return std::move(B);
637 }
638 else
639 {
641
642 for(std::size_t i=0; i < N; ++i) C[i] = A / B[i];
643
644 return C;
645 }
646 }
647
649 template<cgt::std_array_flat_c ArrayType, cgt::numerical_c ScalarType>
650 constexpr decltype(auto) operator+(ArrayType&& A, ScalarType s) noexcept(!cpg::bDetectOverFlow)
651 {
652 constexpr std::size_t N =
653 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
654
656
657 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
658 std::is_rvalue_reference_v<decltype(A)>)
659 {
660 for(std::size_t i{}; i < N; ++i)
661 A[i] = cgt::sbo(A[i]) + cgt::sbo(s);
662
663 return std::move(A);
664 }
665 else
666 {
667 c_t C;
668
669 for(std::size_t i=0; i < N; ++i)
670 C[i] = cgt::sbo(A[i]) + cgt::sbo(s);
671
672 return C;
673 }
674 }
675
676 template<cgt::numerical_c ScalarType, cgt::std_array_flat_c ArrayType>
677 constexpr decltype(auto) operator+(ScalarType s, ArrayType&& A) noexcept(!cpg::bDetectOverFlow)
678 {
679 constexpr std::size_t N =
680 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
681
683
684 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
685 std::is_rvalue_reference_v<decltype(A)>)
686 {
687 for(std::size_t i{}; i < N; ++i)
688 A[i] = cgt::sbo(s) + cgt::sbo(A[i]);
689
690 return std::move(A);
691 }
692 else
693 {
694 c_t C;
695
696 for(std::size_t i=0; i < N; ++i)
697 C[i] = cgt::sbo(s) + cgt::sbo(A[i]);
698
699 return C;
700 }
701 }
702
703 template<cgt::std_array_flat_c ArrayType, cgt::numerical_c ScalarType>
704 constexpr decltype(auto) operator-(ArrayType&& A, ScalarType s) noexcept(!cpg::bDetectOverFlow)
705 {
706 constexpr std::size_t N =
707 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
708
710
711 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
712 std::is_rvalue_reference_v<decltype(A)>)
713 {
714 for(std::size_t i{}; i < N; ++i)
715 A[i] = cgt::sbo(A[i]) - cgt::sbo(s);
716
717 return std::move(A);
718 }
719 else
720 {
721 c_t C;
722
723 for(std::size_t i=0; i < N; ++i)
724 C[i] = cgt::sbo(A[i]) - cgt::sbo(s);
725
726 return C;
727 }
728 }
729
730 template<cgt::numerical_c ScalarType, cgt::std_array_flat_c ArrayType>
731 constexpr decltype(auto) operator-(ScalarType s, ArrayType&& A) noexcept(!cpg::bDetectOverFlow)
732 {
733 constexpr std::size_t N =
734 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
735
737
738 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
739 std::is_rvalue_reference_v<decltype(A)>)
740 {
741 for(std::size_t i{}; i < N; ++i)
742 A[i] = cgt::sbo(s) - cgt::sbo(A[i]);
743
744 return std::move(A);
745 }
746 else
747 {
748 c_t C;
749
750 for(std::size_t i=0; i < N; ++i)
751 C[i] = cgt::sbo(s) - cgt::sbo(A[i]);
752
753 return C;
754 }
755 }
756
757 template<cgt::std_array_flat_c ArrayType, cgt::numerical_c ScalarType>
758 constexpr decltype(auto) operator*(ArrayType&& A, ScalarType s) noexcept(!cpg::bDetectOverFlow)
759 {
760 constexpr std::size_t N =
761 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
762
764
765 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
766 std::is_rvalue_reference_v<decltype(A)>)
767 {
768 for(std::size_t i{}; i < N; ++i)
769 A[i] = cgt::sbo(A[i]) * cgt::sbo(s);
770
771 return std::move(A);
772 }
773 else
774 {
775 c_t C;
776
777 for(std::size_t i=0; i < N; ++i)
778 C[i] = cgt::sbo(A[i]) * cgt::sbo(s);
779
780 return C;
781 }
782 }
783
784 template<cgt::numerical_c ScalarType, cgt::std_array_flat_c ArrayType>
785 constexpr decltype(auto) operator*(ScalarType s, ArrayType&& A) noexcept(!cpg::bDetectOverFlow)
786 {
787 constexpr std::size_t N =
788 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
789
791
792 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
793 std::is_rvalue_reference_v<decltype(A)>)
794 {
795 for(std::size_t i{}; i < N; ++i)
796 A[i] = cgt::sbo(s) * cgt::sbo(A[i]);
797
798 return std::move(A);
799 }
800 else
801 {
802 c_t C;
803
804 for(std::size_t i=0; i < N; ++i)
805 C[i] = cgt::sbo(s) * cgt::sbo(A[i]);
806
807 return C;
808 }
809 }
810
811 template<cgt::std_array_flat_c ArrayType, cgt::numerical_c ScalarType>
812 constexpr decltype(auto) operator/(ArrayType&& A, ScalarType s) noexcept(!cpg::bDetectOverFlow)
813 {
814 constexpr std::size_t N =
815 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
816
818
819 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
820 std::is_rvalue_reference_v<decltype(A)>)
821 {
822 for(std::size_t i{}; i < N; ++i)
823 A[i] = cgt::sbo(A[i]) / cgt::sbo(s);
824
825 return std::move(A);
826 }
827 else
828 {
829 c_t C;
830
831 for(std::size_t i=0; i < N; ++i)
832 C[i] = cgt::sbo(A[i]) / cgt::sbo(s);
833
834 return C;
835 }
836 }
837
838 template<cgt::numerical_c ScalarType, cgt::std_array_flat_c ArrayType>
839 constexpr decltype(auto) operator/(ScalarType s, ArrayType&& A) noexcept(!cpg::bDetectOverFlow)
840 {
841 constexpr std::size_t N =
842 std::tuple_size_v<std::remove_cvref_t<ArrayType>>;
843
845
846 if constexpr(std::same_as<c_t, std::remove_cvref_t<ArrayType>> &&
847 std::is_rvalue_reference_v<decltype(A)>)
848 {
849 for(std::size_t i{}; i < N; ++i)
850 A[i] = cgt::sbo(s) / cgt::sbo(A[i]);
851
852 return std::move(A);
853 }
854 else
855 {
856 c_t C;
857
858 for(std::size_t i=0; i < N; ++i)
859 C[i] = cgt::sbo(s) / cgt::sbo(A[i]);
860
861 return C;
862 }
863 }
864}
865
866#endif
867// end of file
typename hidden::st_std_common_array< std::remove_cvref_t< A >, std::remove_cvref_t< B > >::type common_std_array_t
Definition: cpg_types.hpp:3562
constexpr auto sbo(T &&value) noexcept(!cpg::bDetectOverFlow)
Definition: cpg_types.hpp:2549
constexpr const bool bDetectOverFlow
Definition: cpg_types.hpp:754
auto operator-(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator+(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator/(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator*(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
constexpr decltype(auto) operator&(LeftType &&A, RightType &&B) noexcept(!cpg::bDetectOverFlow)
constexpr decltype(auto) operator%(LeftType &&A, RightType &&B) noexcept(!cpg::bDetectOverFlow)
constexpr auto tuple_size_v
Definition: tpf_types.hpp:1913