Loading...
Searching...
No Matches
math.h
Go to the documentation of this file.
1#ifndef _BBM_NATIVE_MATH_H_
2#define _BBM_NATIVE_MATH_H_
3
4#include <cmath>
5#include <utility>
6
7#include "concepts/util.h"
9#include "util/poly.h"
10#include "backbone/vec.h"
11
12
13/************************************************************************/
14/*! \file math.h
15
16 \brief Extend basic math function to scalar STL and backbone::array types
17
18
19 Satisfies concepts::backbone::has_math_functions
20
21*************************************************************************/
22
23namespace backbone {
24
25 /*** Implementation details for result_t ***/
26 namespace detail {
27 template<typename T, typename... U>
28 struct result_impl
29 {
30 using type = typename result_impl<T, typename result_impl<U...>::type>::type;
31 };
32
33 template<typename T, typename U> requires (!requires(T a, U b) { {a+b}; })
34 struct result_impl<T, U>
35 {
36 using type = std::decay_t<T>;
37 };
38
39
40 template<typename T, typename U> requires requires(T a, U b) { {a+b}; }
41 struct result_impl<T, U>
42 {
43 using type = decltype( std::declval<T>() + std::declval<U>() );
44 };
45 }
46
47 //! \brief determine the mathematical result type; reverts to first argument if '+' is not defined on T...
48 template<typename... T>
49 using result_t = typename detail::result_impl<T...>::type;
50
51 /**********************************************************************/
52 /*! @{ \name Basic STL math functions
53 **********************************************************************/
54 using std::exp;
55 using std::log;
56 using std::sin;
57 using std::asin;
58 using std::cos;
59 using std::acos;
60 using std::tan;
61 using std::atan;
62 using std::sinh;
63 using std::asinh;
64 using std::cosh;
65 using std::acosh;
66 using std::tanh;
67 using std::atanh;
68 using std::ceil;
69 using std::floor;
70 using std::round;
71 using std::copysign;
72 using std::abs;
73 using std::sqrt;
74 using std::cbrt;
75 using std::erf;
76 using std::erfc;
77 using std::tgamma;
78 using std::lgamma;
79 using std::isnan;
80 using std::isinf;
81 using std::isfinite;
82 //! @}
83
84 /**********************************************************************/
85 /*! @{ \name STL math extensions
86 **********************************************************************/
87 template<typename T, typename U> requires (!is_array_v<T>) && requires(T a, U b) { { std::atan2(result_t<T, U>(a), result_t<T,U>(b)) }; }
88 inline constexpr auto atan2(T a, U b) { return std::atan2(result_t<T,U>(a), result_t<T,U>(b)); }
89
90 template<typename T, typename U> requires (!is_array_v<T>) && requires(T a, U b) { { std::fmod(result_t<T, U>(a), result_t<T,U>(b)) }; }
91 inline constexpr auto fmod(T a, U b) { return std::fmod(result_t<T,U>(a), result_t<T,U>(b)); }
92
93 template<typename T, typename U, typename V> requires (!is_array_v<T>) && requires(T a, U b, V c) { { std::lerp(result_t<T, U, V>(a), result_t<T,U,V>(b), result_t<T,U,V>(c)) }; }
94 inline constexpr auto lerp(T a, U b, V c) { return std::lerp(result_t<T,U,V>(a), result_t<T,U,V>(b), result_t<T,U,V>(c)); }
95
96 template<typename T, typename U> requires (!is_array_v<T>) && requires(T a, U b) { { std::pow(result_t<T, U>(a), result_t<T,U>(b)) }; }
97 inline constexpr auto pow(T a, U b) { return std::pow(result_t<T,U>(a), result_t<T,U>(b)); }
98
99 template<typename T, typename U> requires (!is_array_v<T>) && requires(T a, U b) { { std::fmax(result_t<T,U>(a), result_t<T,U>(b)) }; }
100 inline constexpr auto max(T a, U b) { return std::fmax(result_t<T,U>(a),result_t<T,U>(b)); }
101
102 template<typename T, typename U> requires (!is_array_v<T>) && requires(T a, U b) { { std::fmin(result_t<T,U>(a), result_t<T,U>(b)) }; }
103 inline constexpr auto min(T a, U b) { return std::fmin(result_t<T,U>(a),result_t<T,U>(b)); }
104
105 template<typename T, typename L, typename U> requires (!is_array_v<T>) && requires(const T& a, const L& l, const U& u) { { std::clamp(a, T(l), T(u)) }; }
106 inline constexpr auto clamp(const T& a, const L& l, const U& u) { return std::clamp(a, T(l), T(u)); }
107
108 template<typename T>
109 inline constexpr auto rcp(T a) { return 1 / a; }
110
111 template<typename T> requires requires(const T& a) {{std::sqrt(a)};}
112 inline constexpr auto rsqrt(T a) { return rcp(sqrt(a)); }
113
114 template<typename T> requires requires(const T& a) {{std::log(a)};}
115 inline constexpr auto erfinv(T a)
116 {
117 T w = -std::log((1.0-a) * (1.0+a));
118 if(w < 5) return bbm::poly(w - 2.5, 1.50140941, 0.246640727, -0.00417768164, -0.00125372503, 0.00021858087, -4.39150654e-06, -3.5233877e-06, 3.43273939e-07, 2.81022636e-08) * a;
119 else return bbm::poly(sqrt(w) - 3.0, 2.83297682, 1.00167406, 0.00943887047, -0.0076224613, 0.00573950773, -0.00367342844, 0.00134934322, 0.000100950558, -0.000200214257) * a;
120 }
121
122 template<typename T> requires requires(T a) { { std::copysign(T(1), a) }; }
123 inline constexpr auto sign(T a) { return std::copysign(T(1), a); }
124
125 template<typename T> requires requires(T a) { { std::cos(a) }; { std::sin(a) }; }
126 inline constexpr vec2d<T> cossin(T a) { return vec2d<T>(std::cos(a), std::sin(a)); }
127
128 template<typename T> requires requires(T a) { { std::sqrt(std::fmax(a,T(0))) }; }
129 inline constexpr auto safe_sqrt(T a) { return std::sqrt( std::max(a, T(0)) ); }
130
131 template<typename T> requires requires(T a) { { std::asin(std::fmin(T(1), std::fmax(T(-1), a))) }; }
132 inline constexpr auto safe_asin(T a) { return std::asin(std::fmin(T(1), std::fmax(T(-1), a))); }
133
134 template<typename T> requires requires(T a) { { std::acos(std::fmin(T(1), std::fmax(T(-1), a))) }; }
135 inline constexpr auto safe_acos(T a) { return std::acos(std::fmin(T(1), std::fmax(T(-1), a))); }
136
137 template<typename T, typename U> requires std::is_scalar_v<T> && std::is_scalar_v<U>
138 inline constexpr auto eq(T a, U b) { return (a==b); }
139
140 template<typename T, typename U> requires std::is_scalar_v<T> && std::is_scalar_v<U>
141 inline constexpr auto neq(T a, U b) { return (a!=b); }
142 //! @}
143
144
145
146 /*** Implementation detail for invoking a function on arrays ***/
147 namespace detail {
148
149 //! \brief Application of a tertiary function on an array and optionally other arguments
150 template<typename FUNC, typename T, size_t N, typename... U> requires requires(const FUNC& func, const array<T,N>& t, const U&... u) { { func(*bbm::begin(t), (*bbm::begin(u))...) }; }
151 inline auto array_invoke(const FUNC& func, const array<T,N>& t, const U&... u)
152 {
153 using func_t = decltype( func(*t.begin(), (*bbm::begin(u))...) );
154 using result_t = replace_scalar_t< func_t, array<scalar_t<func_t>, N> >;
155 result_t result;
156 bbm::multirange_for([&](auto& r, auto& t, auto&... u) { r = func(t,u...); }, result, t, u...);
157 return result;
158 }
159
160 } // end detail namespace
161
162
163 /**********************************************************************/
164 /*! \brief Helper Macro for defining functions on arrays
165 **********************************************************************/
166#define BBM_ARRAY_FUNC(Func) \
167 template<typename T, typename... U> requires requires(const T& t, const U&... u) {{backbone::detail::array_invoke([](auto&t, auto&... u) { return Func(t, u...); }, t, u...)};} \
168 inline auto Func(const T& t, const U&... u) \
169 { \
170 return backbone::detail::array_invoke([](auto& t, auto&... u) { return Func(t, u...); }, t, u...); \
171 } \
172
173 //! @{ Math Functions on iterable containers
197 BBM_ARRAY_FUNC( safe_sqrt );
198 BBM_ARRAY_FUNC( safe_asin );
199 BBM_ARRAY_FUNC( safe_acos );
200
203 BBM_ARRAY_FUNC( erfinv );
204 BBM_ARRAY_FUNC( tgamma );
205 BBM_ARRAY_FUNC( lgamma );
206
213 BBM_ARRAY_FUNC( copysign );
215
218
221 BBM_ARRAY_FUNC( isfinite );
222
223 template<typename T> requires is_array_v<T> && requires(const T& t) {{ cos(t) }; { sin(t) }; }
224 inline vec2d<T> cossin(const T& a)
225 {
226 return vec2d<T>( cos(a), sin(a) );
227 }
228 //! @}
229
230} // end backbone namespace
231
232#endif /* _BBM_NATIVE_MATH_H_ */
#define BBM_ARRAY_FUNC(Func)
Helper Macro for defining functions on arrays.
Definition: math.h:166
Extensions for STL iterators/ranges.
Random number generator; built on top of Drjit.
Definition: backbone.h:53
constexpr auto eq(T a, U b)
Definition: math.h:138
constexpr auto pow(T a, U b)
Definition: math.h:97
typename detail::result_impl< T... >::type result_t
determine the mathematical result type; reverts to first argument if '+' is not defined on T....
Definition: math.h:49
constexpr auto erfinv(T a)
Definition: math.h:115
auto min(T &&t, U &&u)
min between two variables
Definition: math.h:84
constexpr auto safe_sqrt(T a)
Definition: math.h:129
constexpr auto clamp(const T &a, const L &l, const U &u)
Definition: math.h:106
constexpr auto rsqrt(T a)
Definition: math.h:112
vec2d< T > cossin(const T &a)
cossin
Definition: math.h:107
constexpr auto lerp(T a, U b, V c)
Definition: math.h:94
drjit::Array< T, 2 > vec2d
Definition: vec.h:13
constexpr auto safe_acos(T a)
Definition: math.h:135
auto max(T &&t, U &&u)
max between two variables
Definition: math.h:75
constexpr complex< T > rcp(complex< T > z)
rcp
Definition: complex.h:95
constexpr auto safe_asin(T a)
Definition: math.h:132
constexpr auto neq(T a, U b)
Definition: math.h:141
auto atan2(drjit::Complex< T > a, drjit::Complex< U > b)=delete
delete atan2 to avoid static_error
constexpr auto sign(T a)
Definition: math.h:123
constexpr auto fmod(T a, U b)
Definition: math.h:91
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
void multirange_for(FUNC &&func, Ts &&... containers)
ranged for loop over multiple containers at once
Definition: multirange_for.h:43
auto begin(T &&t)
Definition: iterator_util.h:29
constexpr auto poly(T &&x, T0 &&c0, Ts &&... c)
Compute a polynomial .
Definition: poly.h:35
Compile time polynomial using Horner's method.
Additional basic helper concepts.