Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
math.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 
21 #if !defined(__MITSUBA_CORE_MATH_H_)
22 #define __MITSUBA_CORE_MATH_H_
23 
25 
26 /**
27  * Contains elementary 1D math functions that were either not provided by the standard,
28  * or which are not consistently provided on all platforms/compilers
29  */
30 namespace math {
31 
32 /// Cross-platform implementation of the error function
33 extern MTS_EXPORT_CORE Float erf(Float x);
34 
35 /// Cross-platform implementation of the inverse error function
37 
38 /// sqrt(a^2 + b^2) without range issues (like 'hypot' on compilers that support C99, single precision)
39 extern MTS_EXPORT_CORE float hypot2(float a, float b);
40 
41 /// sqrt(a^2 + b^2) without range issues (like 'hypot' on compilers that support C99, double precision)
42 extern MTS_EXPORT_CORE double hypot2(double a, double b);
43 
44 /// Base-2 logarithm (single precision)
45 extern MTS_EXPORT_CORE float log2(float value);
46 
47 /// Base-2 logarithm (double precision)
48 extern MTS_EXPORT_CORE double log2(double value);
49 
50 /// Generic clamping function
51 template <typename Scalar> inline Scalar clamp(Scalar value, Scalar min, Scalar max) {
52  return std::min(max, std::max(min, value));
53 }
54 
55 /// Linearly interpolate between two values
56 template <typename Scalar> inline Scalar lerp(Scalar t, Scalar v1, Scalar v2) {
57  return ((Scalar) 1 - t) * v1 + t * v2;
58 }
59 
60 /// S-shaped smoothly varying interpolation between two values
61 template <typename Scalar> inline Scalar smoothStep(Scalar min, Scalar max, Scalar value) {
62  Scalar v = clamp((value - min) / (max - min), (Scalar) 0, (Scalar) 1);
63  return v * v * (-2 * v + 3);
64 }
65 
66 /// Always-positive modulo function (assumes b > 0)
67 inline int32_t modulo(int32_t a, int32_t b) {
68  int32_t r = a % b;
69  return (r < 0) ? r+b : r;
70 }
71 
72 /// Always-positive modulo function (assumes b > 0)
73 inline int64_t modulo(int64_t a, int64_t b) {
74  int64_t r = a % b;
75  return (r < 0) ? r+b : r;
76 }
77 
78 #if defined(MTS_AMBIGUOUS_SIZE_T)
79 inline ssize_t modulo(ssize_t a, ssize_t b) {
80  if (sizeof(ssize_t) == 8)
81  return modulo((int64_t) a, (int64_t) b);
82  else
83  return modulo((int32_t) a, (int32_t) b);
84 }
85 #endif
86 
87 /// Always-positive modulo function, single precision version (assumes b > 0)
88 inline float modulo(float a, float b) {
89  float r = std::fmod(a, b);
90  return (r < 0.0f) ? r+b : r;
91 }
92 
93 /// Always-positive modulo function, double precision version (assumes b > 0)
94 inline double modulo(double a, double b) {
95  double r = std::fmod(a, b);
96  return (r < 0.0) ? r+b : r;
97 }
98 
99 /// Integer floor function (single precision)
100 template <typename Scalar> inline int floorToInt(Scalar value) { return (int) std::floor(value); }
101 
102 /// Integer ceil function (single precision)
103 template <typename Scalar> inline int ceilToInt(Scalar value) { return (int) std::ceil(value); }
104 
105 /// Integer round function (single precision)
106 inline int roundToInt(float value) {
107  #if defined(__MSVC__)
108  return (int) (value < 0.0f ? std::ceil(value - 0.5f) : std::floor(value + 0.5f));
109  #else
110  return (int) ::roundf(value);
111  #endif
112 }
113 
114 /// Integer round function (double precision)
115 inline int roundToInt(double value) {
116  #if defined(__MSVC__)
117  return (int) (value < 0.0 ? std::ceil(value - 0.5) : std::floor(value + 0.5));
118  #else
119  return (int) ::round(value);
120  #endif
121 }
122 
123 /// Base-2 logarithm (32-bit integer version)
124 extern MTS_EXPORT_CORE int log2i(uint32_t value);
125 
126 /// Base-2 logarithm (64-bit integer version)
127 extern MTS_EXPORT_CORE int log2i(uint64_t value);
128 
129 #if defined(MTS_AMBIGUOUS_SIZE_T)
130 inline int log2i(size_t value) {
131  if (sizeof(size_t) == 8)
132  return log2i((uint64_t) value);
133  else
134  return log2i((uint32_t) value);
135 }
136 #endif
137 
138 /// Check if an integer is a power of two (unsigned 32 bit version)
139 inline bool isPowerOfTwo(uint32_t i) { return (i & (i-1)) == 0; }
140 
141 /// Check if an integer is a power of two (signed 32 bit version)
142 inline bool isPowerOfTwo(int32_t i) { return i > 0 && (i & (i-1)) == 0; }
143 
144 /// Check if an integer is a power of two (64 bit version)
145 inline bool isPowerOfTwo(uint64_t i) { return (i & (i-1)) == 0; }
146 
147 /// Check if an integer is a power of two (signed 64 bit version)
148 inline bool isPowerOfTwo(int64_t i) { return i > 0 && (i & (i-1)) == 0; }
149 
150 #if defined(MTS_AMBIGUOUS_SIZE_T)
151 inline bool isPowerOfTwo(size_t value) {
152  if (sizeof(size_t) == 8) /// will be optimized away
153  return isPowerOfTwo((uint64_t) value);
154  else
155  return isPowerOfTwo((uint32_t) value);
156 }
157 #endif
158 
159 /// Round an integer to the next power of two
161 
162 /// Round an integer to the next power of two (64 bit version)
163 extern MTS_EXPORT_CORE uint64_t roundToPowerOfTwo(uint64_t i);
164 
165 #if defined(MTS_AMBIGUOUS_SIZE_T)
166 /// Round an integer to the next power of two
167 inline size_t roundToPowerOfTwo(size_t value) {
168  if (sizeof(size_t) == 8) /// will be optimized away
169  return (size_t) roundToPowerOfTwo((uint64_t) value);
170  else
171  return (size_t) roundToPowerOfTwo((uint32_t) value);
172 }
173 #endif
174 
175 #if defined(__LINUX__) && defined(__x86_64__)
176  /*
177  The Linux/x86_64 single precision implementations of 'exp'
178  and 'log' suffer from a serious performance regression.
179  It is about 5x faster to use the double-precision versions
180  with the extra overhead of the involved FP conversion.
181 
182  Until this is fixed, the following aliases make sure that
183  the fastest implementation is used in every case.
184  */
185  inline float fastexp(float value) {
186  return (float) ::exp((double) value);
187  }
188 
189  inline double fastexp(double value) {
190  return ::exp(value);
191  }
192 
193  inline float fastlog(float value) {
194  return (float) ::log((double) value);
195  }
196 
197  inline double fastlog(double value) {
198  return ::log(value);
199  }
200 #else
201  inline float fastexp(float value) {
202  return ::expf(value);
203  }
204 
205  inline double fastexp(double value) {
206  return ::exp(value);
207  }
208 
209  inline float fastlog(float value) {
210  return ::logf(value);
211  }
212 
213  inline double fastlog(double value) {
214  return ::log(value);
215  }
216 #endif
217 
218 #if defined(_GNU_SOURCE)
219  inline void sincos(float theta, float *sin, float *cos) {
220  ::sincosf(theta, sin, cos);
221  }
222 
223  inline void sincos(double theta, double *sin, double *cos) {
224  ::sincos(theta, sin, cos);
225  }
226 
227 #else
228  inline void sincos(float theta, float *_sin, float *_cos) {
229  *_sin = sinf(theta);
230  *_cos = cosf(theta);
231  }
232 
233  inline void sincos(double theta, double *_sin, double *_cos) {
234  *_sin = sin(theta);
235  *_cos = cos(theta);
236  }
237 #endif
238 
239  /// Arcsine variant that gracefully handles arguments > 1 that are due to roundoff errors
240  inline float safe_asin(float value) {
241  return std::asin(std::min(1.0f, std::max(-1.0f, value)));
242  }
243 
244  /// Arcsine variant that gracefully handles arguments > 1 that are due to roundoff errors
245  inline double safe_asin(double value) {
246  return std::asin(std::min(1.0, std::max(-1.0, value)));
247  }
248 
249  /// Arccosine variant that gracefully handles arguments > 1 that are due to roundoff errors
250  inline float safe_acos(float value) {
251  return std::acos(std::min(1.0f, std::max(-1.0f, value)));
252  }
253 
254  /// Arccosine variant that gracefully handles arguments > 1 that are due to roundoff errors
255  inline double safe_acos(double value) {
256  return std::acos(std::min(1.0, std::max(-1.0, value)));
257  }
258 
259  /// Square root variant that gracefully handles arguments < 0 that are due to roundoff errors
260  inline float safe_sqrt(float value) {
261  return std::sqrt(std::max(0.0f, value));
262  }
263 
264  /// Square root variant that gracefully handles arguments < 0 that are due to roundoff errors
265  inline double safe_sqrt(double value) {
266  return std::sqrt(std::max(0.0, value));
267  }
268 
269  /// Simple signum function -- note that it returns the FP sign of the input (and never zero)
270  inline Float signum(Float value) {
271  #if defined(__WINDOWS__)
272  return (Float) _copysign(1.0, value);
273  #elif defined(SINGLE_PRECISION)
274  return copysignf((float) 1.0, value);
275  #elif defined(DOUBLE_PRECISION)
276  return copysign((double) 1.0, value);
277  #endif
278  }
279 
280  /// Cast to single precision and round up if not exactly representable (passthrough)
281  inline float castflt_up(float val) { return val; }
282 
283  /// Cast to single precision and round up if not exactly representable
284  inline float castflt_up(double val) {
285  union {
286  float a;
287  int b;
288  };
289 
290  a = (float) val;
291  if ((double) a < val)
292  b += a < 0 ? -1 : 1;
293  return a;
294  }
295 
296  /// Cast to single precision and round down if not exactly representable (passthrough)
297  inline float castflt_down(float val) { return val; }
298 
299  /// Cast to single precision and round down if not exactly representable
300  inline float castflt_down(double val) {
301  union {
302  float a;
303  int b;
304  };
305 
306  a = (float) val;
307  if ((double) a > val)
308  b += a > 0 ? -1 : 1;
309  return a;
310  }
311 }; /* namespace math */
312 
314 
315 #endif /* __MITSUBA_CORE_MATH_H_ */
MTS_EXPORT_CORE float hypot2(float a, float b)
sqrt(a^2 + b^2) without range issues (like &#39;hypot&#39; on compilers that support C99, single precision) ...
float fastlog(float value)
Definition: math.h:209
float castflt_up(float val)
Cast to single precision and round up if not exactly representable (passthrough)
Definition: math.h:281
int floorToInt(Scalar value)
Integer floor function (single precision)
Definition: math.h:100
bool isPowerOfTwo(uint32_t i)
Check if an integer is a power of two (unsigned 32 bit version)
Definition: math.h:139
float safe_asin(float value)
Arcsine variant that gracefully handles arguments &gt; 1 that are due to roundoff errors.
Definition: math.h:240
#define MTS_EXPORT_CORE
Definition: getopt.h:29
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
int32_t modulo(int32_t a, int32_t b)
Always-positive modulo function (assumes b &gt; 0)
Definition: math.h:67
MTS_EXPORT_CORE uint32_t roundToPowerOfTwo(uint32_t i)
Round an integer to the next power of two.
MTS_EXPORT_CORE float log2(float value)
Base-2 logarithm (single precision)
Scalar lerp(Scalar t, Scalar v1, Scalar v2)
Linearly interpolate between two values.
Definition: math.h:56
int ceilToInt(Scalar value)
Integer ceil function (single precision)
Definition: math.h:103
float safe_sqrt(float value)
Square root variant that gracefully handles arguments &lt; 0 that are due to roundoff errors...
Definition: math.h:260
MTS_EXPORT_CORE Float erfinv(Float x)
Cross-platform implementation of the inverse error function.
float safe_acos(float value)
Arccosine variant that gracefully handles arguments &gt; 1 that are due to roundoff errors.
Definition: math.h:250
void sincos(float theta, float *_sin, float *_cos)
Definition: math.h:228
float castflt_down(float val)
Cast to single precision and round down if not exactly representable (passthrough) ...
Definition: math.h:297
MTS_EXPORT_CORE int log2i(uint32_t value)
Base-2 logarithm (32-bit integer version)
float fastexp(float value)
Definition: math.h:201
int roundToInt(float value)
Integer round function (single precision)
Definition: math.h:106
Scalar smoothStep(Scalar min, Scalar max, Scalar value)
S-shaped smoothly varying interpolation between two values.
Definition: math.h:61
#define MTS_NAMESPACE_END
Definition: platform.h:138
Float signum(Float value)
Simple signum function – note that it returns the FP sign of the input (and never zero) ...
Definition: math.h:270
MTS_EXPORT_CORE Float erf(Float x)
Cross-platform implementation of the error function.
Scalar clamp(Scalar value, Scalar min, Scalar max)
Generic clamping function.
Definition: math.h:51