1 #pragma once
2 
3 #include <algorithm>
4 #include <limits>
5 #include <cmath>
6 #include <cstdint>
7 #include <array>
8 
9 namespace rtengine
10 {
11 
12 constexpr int MAXVAL = 0xffff;
13 constexpr float MAXVALF = static_cast<float>(MAXVAL);  // float version of MAXVAL
14 constexpr double MAXVALD = static_cast<double>(MAXVAL); // double version of MAXVAL
15 
16 constexpr double RT_PI = 3.14159265358979323846; // pi
17 constexpr double RT_PI_2 = 1.57079632679489661923; // pi/2
18 constexpr double RT_PI_180 = 0.017453292519943295769; // pi/180
19 constexpr double RT_1_PI = 0.31830988618379067154; // 1/pi
20 constexpr double RT_2_PI = 0.63661977236758134308; // 2/pi
21 constexpr double RT_SQRT1_2 = 0.70710678118654752440; // 1/sqrt(2)
22 
23 constexpr double RT_INFINITY = std::numeric_limits<double>::infinity();
24 constexpr double RT_NAN = std::numeric_limits<double>::quiet_NaN();
25 
26 constexpr float RT_PI_F = RT_PI;
27 constexpr float RT_PI_F_2 = RT_PI_2;
28 constexpr float RT_PI_F_180 = RT_PI_180;
29 constexpr float RT_1_PI_F = RT_1_PI;
30 constexpr float RT_2_PI_F = RT_2_PI;
31 
32 constexpr float RT_INFINITY_F = std::numeric_limits<float>::infinity();
33 constexpr float RT_NAN_F = std::numeric_limits<float>::quiet_NaN();
34 
35 template<typename T>
SQR(T x)36 constexpr T SQR(T x)
37 {
38     return x * x;
39 }
40 
41 template<typename T>
pow4(T x)42 constexpr T pow4(T x)
43 {
44     return SQR(SQR(x));
45 }
46 
47 template<typename T>
min(const T & a)48 constexpr const T& min(const T& a)
49 {
50     return a;
51 }
52 
53 template<typename T>
min(const T & a,const T & b)54 constexpr const T& min(const T& a, const T& b)
55 {
56     return b < a ? b : a;
57 }
58 
59 template<typename T, typename... ARGS>
min(const T & a,const T & b,const ARGS &...args)60 constexpr const T& min(const T& a, const T& b, const ARGS&... args)
61 {
62     return min(min(a, b), min(args...));
63 }
64 
65 template<typename T>
max(const T & a)66 constexpr const T& max(const T& a)
67 {
68     return a;
69 }
70 
71 template<typename T>
max(const T & a,const T & b)72 constexpr const T& max(const T& a, const T& b)
73 {
74     return a < b ? b : a;
75 }
76 
77 template<typename T, typename... ARGS>
max(const T & a,const T & b,const ARGS &...args)78 constexpr const T& max(const T& a, const T& b, const ARGS&... args)
79 {
80     return max(max(a, b), max(args...));
81 }
82 
83 template<typename T>
LIM(const T & val,const T & low,const T & high)84 constexpr const T& LIM(const T& val, const T& low, const T& high)
85 {
86     return max(low, min(val, high));
87 }
88 
89 template<typename T>
LIM01(const T & a)90 constexpr T LIM01(const T& a)
91 {
92     return max(T(0), min(a, T(1)));
93 }
94 
95 template<typename T>
CLIP(const T & a)96 constexpr T CLIP(const T& a)
97 {
98     return LIM(a, static_cast<T>(0), static_cast<T>(MAXVAL));
99 }
100 
101 template <typename T>
SGN(const T & a)102 constexpr T SGN(const T& a)
103 {
104     // returns -1 for a < 0, 0 for a = 0 and +1 for a > 0
105     return (T(0) < a) - (a < T(0));
106 }
107 
108 template<typename T>
intp(T a,T b,T c)109 constexpr T intp(T a, T b, T c)
110 {
111     // calculate a * b + (1 - a) * c
112     // following is valid:
113     // intp(a, b+x, c+x) = intp(a, b, c) + x
114     // intp(a, b*x, c*x) = intp(a, b, c) * x
115     return a * (b - c) + c;
116 }
117 
118 template<typename T>
norm1(const T & x,const T & y)119 inline T norm1(const T& x, const T& y)
120 {
121     return std::abs(x) + std::abs(y);
122 }
123 
124 template<typename T>
norm2(const T & x,const T & y)125 inline T norm2(const T& x, const T& y)
126 {
127     return std::sqrt(x * x + y * y);
128 }
129 
130 template< typename T >
norminf(const T & x,const T & y)131 inline T norminf(const T& x, const T& y)
132 {
133     return max(std::abs(x), std::abs(y));
134 }
135 
float2uint16range(float d)136 constexpr int float2uint16range(float d)
137 {
138     // clips input to [0;65535] and rounds
139     return CLIP(d) + 0.5f;
140 }
141 
uint16ToUint8Rounded(std::uint16_t i)142 constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i)
143 {
144     return ((i + 128) - ((i + 128) >> 8)) >> 8;
145 }
146 
147 template <typename T>
148 constexpr bool OOG(const T &val, const T &high=T(MAXVAL))
149 {
150     return (val < T(0)) || (val > high);
151 }
152 
153 template <typename T>
setUnlessOOG(T & out,const T & val)154 void setUnlessOOG(T &out, const T &val)
155 {
156     if (!OOG(out)) {
157         out = val;
158     }
159 }
160 
161 
162 template <typename T>
invertMatrix(const std::array<std::array<T,3>,3> & in,std::array<std::array<T,3>,3> & out)163 bool invertMatrix(const std::array<std::array<T, 3>, 3> &in, std::array<std::array<T, 3>, 3> &out)
164 {
165     const T res00 = in[1][1] * in[2][2] - in[2][1] * in[1][2];
166     const T res10 = in[2][0] * in[1][2] - in[1][0] * in[2][2];
167     const T res20 = in[1][0] * in[2][1] - in[2][0] * in[1][1];
168 
169     const T det = in[0][0] * res00 + in[0][1] * res10 + in[0][2] * res20;
170 
171     if (std::abs(det) < 1.0e-10) {
172         return false;
173     }
174 
175     out[0][0] = res00 / det;
176     out[0][1] = (in[2][1] * in[0][2] - in[0][1] * in[2][2]) / det;
177     out[0][2] = (in[0][1] * in[1][2] - in[1][1] * in[0][2]) / det;
178     out[1][0] = res10 / det;
179     out[1][1] = (in[0][0] * in[2][2] - in[2][0] * in[0][2]) / det;
180     out[1][2] = (in[1][0] * in[0][2] - in[0][0] * in[1][2]) / det;
181     out[2][0] = res20 / det;
182     out[2][1] = (in[2][0] * in[0][1] - in[0][0] * in[2][1]) / det;
183     out[2][2] = (in[0][0] * in[1][1] - in[1][0] * in[0][1]) / det;
184 
185     return true;
186 }
187 
188 
189 template <typename T>
dotProduct(const std::array<std::array<T,3>,3> & a,const std::array<std::array<T,3>,3> & b)190 std::array<std::array<T, 3>, 3> dotProduct(const std::array<std::array<T, 3>, 3> &a, const std::array<std::array<T, 3>, 3> &b)
191 {
192     std::array<std::array<T, 3>, 3> res;
193 
194     for (int i = 0; i < 3; ++i) {
195         for (int j = 0; j < 3; ++j) {
196             res[i][j] = 0;
197 
198             for (int k = 0; k < 3; ++k) {
199                 res[i][j] += a[i][k] * b[k][j];
200             }
201         }
202     }
203 
204     return res;
205 }
206 
207 
208 template <typename T>
dotProduct(const std::array<std::array<T,3>,3> & a,const std::array<T,3> & b)209 std::array<T, 3> dotProduct(const std::array<std::array<T, 3>, 3> &a, const std::array<T, 3> &b)
210 {
211     std::array<T, 3> res;
212 
213     for (int i = 0; i < 3; ++i) {
214         res[i] = 0;
215         for (int k = 0; k < 3; ++k) {
216             res[i] += a[i][k] * b[k];
217         }
218     }
219 
220     return res;
221 }
222 
223 
224 template <typename T>
lin2log(T x,T base)225 T lin2log(T x, T base)
226 {
227     constexpr T one(1);
228     return std::log(x * (base - one) + one) / std::log(base);
229 }
230 
231 
232 template <typename T>
log2lin(T x,T base)233 T log2lin(T x, T base)
234 {
235     constexpr T one(1);
236     return (std::pow(base, x) - one) / (base - one);
237 }
238 
239 }
240 
241