The spica renderer
math.h
1 #ifndef _MSC_VER
2 #pragma once
3 #endif
4 
5 #ifndef _SPICA_MATH_H_
6 #define _SPICA_MATH_H_
7 
8 #include "common.h"
9 
10 namespace spica {
11 
12 namespace math {
13 
14 inline double erfinv(double x) {
15  double w, p;
16  x = clamp(x, -0.99999, 0.99999);
17  w = -std::log((1 - x) * (1 + x));
18  if (w < 5) {
19  w = w - 2.5f;
20  p = 2.81022636e-08f;
21  p = 3.43273939e-07f + p * w;
22  p = -3.5233877e-06f + p * w;
23  p = -4.39150654e-06f + p * w;
24  p = 0.00021858087f + p * w;
25  p = -0.00125372503f + p * w;
26  p = -0.00417768164f + p * w;
27  p = 0.246640727f + p * w;
28  p = 1.50140941f + p * w;
29  } else {
30  w = std::sqrt(w) - 3;
31  p = -0.000200214257f;
32  p = 0.000100950558f + p * w;
33  p = 0.00134934322f + p * w;
34  p = -0.00367342844f + p * w;
35  p = 0.00573950773f + p * w;
36  p = -0.0076224613f + p * w;
37  p = 0.00943887047f + p * w;
38  p = 1.00167406f + p * w;
39  p = 2.83297682f + p * w;
40  }
41  return p * x;
42 }
43 
44 inline double erf(double x) {
45  // constants
46  double a1 = 0.254829592f;
47  double a2 = -0.284496736f;
48  double a3 = 1.421413741f;
49  double a4 = -1.453152027f;
50  double a5 = 1.061405429f;
51  double p = 0.3275911f;
52 
53  // Save the sign of x
54  int sign = 1;
55  if (x < 0) sign = -1;
56  x = std::abs(x);
57 
58  // A&S formula 7.1.26
59  double t = 1 / (1 + p * x);
60  double y =
61  1 -
62  (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * std::exp(-x * x);
63 
64  return sign * y;
65 }
66 
67 } // namespace math
68 
69 } // namespace spica
70 
71 #endif // _SPICA_MATH_H_