Stratax 0.3.1
Loading...
Searching...
No Matches
Math.hpp
1#pragma once
2
3#include <cmath>
4#include <type_traits>
5#include <cstddef>
6
7#include <stratax/core/ArrayTraits.hpp>
8#include <stratax/core/dtypes/Concepts.hpp>
9#include <stratax/core/dtypes/Types.hpp>
10#include <stratax/ops/Broadcasting.hpp>
11
12namespace stratax::core::math_detail {
13
20template<Array A, DType Result, typename Op>
21auto unary_op(const A& arr, Op op)
22{
23 using result_type =
24 stratax::core::rebind_array_t<A, Result>;
25
26 result_type result(arr.shape());
27
28 for (std::size_t i = 0; i < arr.size(); ++i)
29 {
30 result[i] = static_cast<Result>(op(arr[i]));
31 }
32
33 return result;
34}
35
37template<typename T>
39{
41 using type = std::remove_cvref_t<T>;
42};
43
45template<Integral T>
46struct MathResult<T>
47{
49 using type = dtype::float64;
50};
51
52template<typename T>
53using math_result_t =
55
62template<Array A, typename Op>
63auto standard_math_op(const A& arr, Op op)
64{
65 using result_value_type =
66 math_result_t<typename A::value_type>;
67
68 return unary_op<A, result_value_type>(arr, op);
69}
70
72template<typename L, typename R>
74{
77 promote_t<
78 std::remove_cvref_t<L>,
79 std::remove_cvref_t<R>>;
80
82 using type = std::conditional_t<
84 dtype::float64,
86};
87
88template<typename L, typename R>
89using pow_result_t =
90 typename PowResult<L, R>::type;
91
93template<typename T>
95{
97 using type = std::remove_cvref_t<T>;
98};
99
101template<typename T>
102requires (
104 DTypeKind::Complex
105)
107{
109 using type =
110 complex_component_t<std::remove_cvref_t<T>>;
111};
112
113template<typename T>
114using abs_result_t =
115 typename AbsResult<std::remove_cvref_t<T>>::type;
116
117} // namespace stratax::core::math_detail
118
119namespace stratax::core {
120
122template<Array A>
124auto sqrt(const A& arr)
125{
126 return math_detail::standard_math_op(
127 arr, [](const auto& value)
128 {
129 return std::sqrt(value);
130 });
131}
132
134template<Array A>
136auto cbrt(const A& arr)
137{
138 return math_detail::standard_math_op(
139 arr, [](const auto& value)
140 {
141 return std::cbrt(value);
142 });
143}
144
146template<Array A>
148auto exp(const A& arr)
149{
150 return math_detail::standard_math_op(
151 arr, [](const auto& value)
152 {
153 return std::exp(value);
154 });
155}
156
158template<Array A>
160auto exp2(const A& arr)
161{
162 return math_detail::standard_math_op(
163 arr, [](const auto& value)
164 {
165 return std::exp2(value);
166 });
167}
168
170template<Array A>
172auto expm1(const A& arr)
173{
174 return math_detail::standard_math_op(
175 arr, [](const auto& value)
176 {
177 return std::expm1(value);
178 });
179}
180
182template<Array A>
184auto log(const A& arr)
185{
186 return math_detail::standard_math_op(
187 arr, [](const auto& value)
188 {
189 return std::log(value);
190 });
191}
192
194template<Array A>
196auto log2(const A& arr)
197{
198 return math_detail::standard_math_op(
199 arr, [](const auto& value)
200 {
201 return std::log2(value);
202 });
203}
204
206template<Array A>
208auto log10(const A& arr)
209{
210 return math_detail::standard_math_op(
211 arr, [](const auto& value)
212 {
213 return std::log10(value);
214 });
215}
216
218template<Array A>
220auto log1p(const A& arr)
221{
222 return math_detail::standard_math_op(
223 arr, [](const auto& value)
224 {
225 return std::log1p(value);
226 });
227}
228
230template<Array A>
232auto logb(const A& arr)
233{
234 return math_detail::standard_math_op(
235 arr, [](const auto& value)
236 {
237 return std::logb(value);
238 });
239}
240
242template<Array A>
244auto sin(const A& arr)
245{
246 return math_detail::standard_math_op(
247 arr, [](const auto& value)
248 {
249 return std::sin(value);
250 });
251}
252
254template<Array A>
256auto cos(const A& arr)
257{
258 return math_detail::standard_math_op(
259 arr, [](const auto& value)
260 {
261 return std::cos(value);
262 });
263}
264
266template<Array A>
268auto tan(const A& arr)
269{
270 return math_detail::standard_math_op(
271 arr, [](const auto& value)
272 {
273 return std::tan(value);
274 });
275}
276
278template<Array A>
280auto asin(const A& arr)
281{
282 return math_detail::standard_math_op(
283 arr, [](const auto& value)
284 {
285 return std::asin(value);
286 });
287}
288
290template<Array A>
292auto acos(const A& arr)
293{
294 return math_detail::standard_math_op(
295 arr, [](const auto& value)
296 {
297 return std::acos(value);
298 });
299}
300
302template<Array A>
304auto atan(const A& arr)
305{
306 return math_detail::standard_math_op(
307 arr, [](const auto& value)
308 {
309 return std::atan(value);
310 });
311}
312
314template<Array A>
316auto sinh(const A& arr)
317{
318 return math_detail::standard_math_op(
319 arr, [](const auto& value)
320 {
321 return std::sinh(value);
322 });
323}
324
326template<Array A>
328auto cosh(const A& arr)
329{
330 return math_detail::standard_math_op(
331 arr, [](const auto& value)
332 {
333 return std::cosh(value);
334 });
335}
336
338template<Array A>
340auto tanh(const A& arr)
341{
342 return math_detail::standard_math_op(
343 arr, [](const auto& value)
344 {
345 return std::tanh(value);
346 });
347}
348
350template<Array A>
352auto asinh(const A& arr)
353{
354 return math_detail::standard_math_op(
355 arr, [](const auto& value)
356 {
357 return std::asinh(value);
358 });
359}
360
362template<Array A>
364auto acosh(const A& arr)
365{
366 return math_detail::standard_math_op(
367 arr, [](const auto& value)
368 {
369 return std::acosh(value);
370 });
371}
372
374template<Array A>
376auto atanh(const A& arr)
377{
378 return math_detail::standard_math_op(
379 arr, [](const auto& value)
380 {
381 return std::atanh(value);
382 });
383}
384
386template<Array A>
388auto erf(const A& arr)
389{
390 return math_detail::standard_math_op(
391 arr, [](const auto& value)
392 {
393 return std::erf(value);
394 });
395}
396
398template<Array A>
400auto erfc(const A& arr)
401{
402 return math_detail::standard_math_op(
403 arr, [](const auto& value)
404 {
405 return std::erfc(value);
406 });
407}
408
410template<Array A>
412auto tgamma(const A& arr)
413{
414 return math_detail::standard_math_op(
415 arr, [](const auto& value)
416 {
417 return std::tgamma(value);
418 });
419}
420
422template<Array A>
424auto lgamma(const A& arr)
425{
426 return math_detail::standard_math_op(
427 arr, [](const auto& value)
428 {
429 return std::lgamma(value);
430 });
431}
432
438template<Array A>
440auto abs(const A& arr)
441{
442 using result_value_type =
443 math_detail::abs_result_t<typename A::value_type>;
444
445 return math_detail::unary_op<A, result_value_type>(
446 arr,
447 [](const auto& value)
448 {
449 using std::abs;
450 return abs(value);
451 });
452}
453
455template<Array A>
457auto floor(const A& arr)
458{
459 using result_value_type = typename A::value_type;
460
461 return math_detail::unary_op<A, result_value_type>(
462 arr,
463 [](const auto& value)
464 {
465 return std::floor(value);
466 });
467}
468
470template<Array A>
472auto ceil(const A& arr)
473{
474 using result_value_type = typename A::value_type;
475
476 return math_detail::unary_op<A, result_value_type>(
477 arr,
478 [](const auto& value)
479 {
480 return std::ceil(value);
481 });
482}
483
485template<Array A>
487auto trunc(const A& arr)
488{
489 using result_value_type = typename A::value_type;
490
491 return math_detail::unary_op<A, result_value_type>(
492 arr,
493 [](const auto& value)
494 {
495 return std::trunc(value);
496 });
497}
498
500template<Array A>
502auto round(const A& arr)
503{
504 using result_value_type = typename A::value_type;
505
506 return math_detail::unary_op<A, result_value_type>(
507 arr,
508 [](const auto& value)
509 {
510 return std::round(value);
511 });
512}
513
515template<Array A>
517auto nearbyint(const A& arr)
518{
519 using result_value_type = typename A::value_type;
520
521 return math_detail::unary_op<A, result_value_type>(
522 arr,
523 [](const auto& value)
524 {
525 return std::nearbyint(value);
526 });
527}
528
530template<Array A>
532auto rint(const A& arr)
533{
534 using result_value_type = typename A::value_type;
535
536 return math_detail::unary_op<A, result_value_type>(
537 arr,
538 [](const auto& value)
539 {
540 return std::rint(value);
541 });
542}
543
550template<Array L, Array R>
551auto pow(const L& lhs, const R& rhs)
552{
553 using result_type =
554 math_detail::pow_result_t<
555 typename L::value_type,
556 typename R::value_type>;
557
558 return broadcasted_op<result_type>(
559 lhs,
560 rhs,
561 [](const auto& a, const auto& b)
562 {
563 return std::pow(a, b);
564 });
565}
566
573template<Array L, Array R>
574auto atan2(const L& lhs, const R& rhs)
575{
576 using result_type =
577 math_detail::pow_result_t<
578 typename L::value_type,
579 typename R::value_type>;
580
581 return broadcasted_op<result_type>(
582 lhs,
583 rhs,
584 [](const auto& a, const auto& b)
585 {
586 return std::atan2(a, b);
587 });
588}
589
591template<Array L, Array R>
592auto hypot(const L& lhs, const R& rhs)
593{
594 using result_type =
595 math_detail::pow_result_t<
596 typename L::value_type,
597 typename R::value_type>;
598
599 return broadcasted_op<result_type>(
600 lhs,
601 rhs,
602 [](const auto& a, const auto& b)
603 {
604 return std::hypot(a, b);
605 });
606}
607
609template<Array L, Array R>
610auto fmod(const L& lhs, const R& rhs)
611{
612 using result_type =
613 math_detail::pow_result_t<
614 typename L::value_type,
615 typename R::value_type>;
616
617 return broadcasted_op<result_type>(
618 lhs,
619 rhs,
620 [](const auto& a, const auto& b)
621 {
622 return std::fmod(a, b);
623 });
624}
625
627template<Array L, Array R>
628auto remainder(const L& lhs, const R& rhs)
629{
630 using result_type =
631 math_detail::pow_result_t<
632 typename L::value_type,
633 typename R::value_type>;
634
635 return broadcasted_op<result_type>(
636 lhs,
637 rhs,
638 [](const auto& a, const auto& b)
639 {
640 return std::remainder(a, b);
641 });
642}
643
645template<Array L, Array R>
646auto copysign(const L& lhs, const R& rhs)
647{
648 using result_type =
649 math_detail::pow_result_t<
650 typename L::value_type,
651 typename R::value_type>;
652
653 return broadcasted_op<result_type>(
654 lhs,
655 rhs,
656 [](const auto& a, const auto& b)
657 {
658 return std::copysign(a, b);
659 });
660}
661
663template<Array L, Array R>
664auto fmax(const L& lhs, const R& rhs)
665{
666 using result_type =
667 math_detail::pow_result_t<
668 typename L::value_type,
669 typename R::value_type>;
670
671 return broadcasted_op<result_type>(
672 lhs,
673 rhs,
674 [](const auto& a, const auto& b)
675 {
676 return std::fmax(a, b);
677 });
678}
679
681template<Array L, Array R>
682auto fmin(const L& lhs, const R& rhs)
683{
684 using result_type =
685 math_detail::pow_result_t<
686 typename L::value_type,
687 typename R::value_type>;
688
689 return broadcasted_op<result_type>(
690 lhs,
691 rhs,
692 [](const auto& a, const auto& b)
693 {
694 return std::fmin(a, b);
695 });
696}
697
699template<Array L, Array R>
700requires (
703)
704auto fdim(const L& lhs, const R& rhs)
705{
706 using result_type =
707 math_detail::pow_result_t<
708 typename L::value_type,
709 typename R::value_type>;
710
711 return broadcasted_op<result_type>(
712 lhs,
713 rhs,
714 [](const auto& a, const auto& b)
715 {
716 return std::fdim(a, b);
717 });
718}
719
721template<Array L, Array R>
722requires (
725)
726auto nextafter(const L& lhs, const R& rhs)
727{
728 using result_type =
729 math_detail::pow_result_t<
730 typename L::value_type,
731 typename R::value_type>;
732
733 return broadcasted_op<result_type>(
734 lhs,
735 rhs,
736 [](const auto& a, const auto& b)
737 {
738 return std::nextafter(a, b);
739 });
740}
741
742} // namespace stratax::core
Provides compile-time metadata for a supported Stratax dtype.
complex_component_t< std::remove_cvref_t< T > > type
Real magnitude dtype corresponding to the complex input.
Definition Math.hpp:110
Preserves the dtype of a real absolute-value operation.
Definition Math.hpp:95
std::remove_cvref_t< T > type
Absolute-value result dtype.
Definition Math.hpp:97
dtype::float64 type
Floating-point result dtype used for integral input.
Definition Math.hpp:49
Maps a non-integral input dtype to the same result dtype.
Definition Math.hpp:39
std::remove_cvref_t< T > type
Result dtype for a standard unary math operation.
Definition Math.hpp:41
Determines the common result dtype for a binary math operation.
Definition Math.hpp:74
promote_t< std::remove_cvref_t< L >, std::remove_cvref_t< R > > promoted_type
Dtype obtained from the ordinary Stratax promotion rules.
Definition Math.hpp:79
std::conditional_t< Integral< promoted_type >, dtype::float64, promoted_type > type
Promoted dtype, with integral-only results changed to float64.
Definition Math.hpp:85