WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
erf.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2024 Keith O'Hara
4 ##
5 ## This file is part of the GCE-Math C++ library.
6 ##
7 ## Licensed under the Apache License, Version 2.0 (the "License");
8 ## you may not use this file except in compliance with the License.
9 ## You may obtain a copy of the License at
10 ##
11 ## http://www.apache.org/licenses/LICENSE-2.0
12 ##
13 ## Unless required by applicable law or agreed to in writing, software
14 ## distributed under the License is distributed on an "AS IS" BASIS,
15 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ## See the License for the specific language governing permissions and
17 ## limitations under the License.
18 ##
19 ################################################################################*/
20
21/*
22 * compile-time error function
23 */
24
25#ifndef _gcem_erf_HPP
26#define _gcem_erf_HPP
27
28#include <cmath>
29#include <type_traits>
30
31namespace gcem
32{
33
34namespace internal
35{
36
37// see
38// http://functions.wolfram.com/GammaBetaErf/Erf/10/01/0007/
39
40#if __cplusplus >= 201402L // C++14 version
41
42template<typename T>
43constexpr
44T
45erf_cf_large_recur(const T x, const int depth_end)
46noexcept
47{
48 int depth = GCEM_ERF_MAX_ITER - 1;
49 T res = x;
50
51 while (depth > depth_end - 1) {
52 res = x + 2 * depth / res;
53
54 --depth;
55 }
56
57 return res;
58}
59
60#else // C++11 version
61
62template<typename T>
63constexpr
64T
65erf_cf_large_recur(const T x, const int depth)
66noexcept
67{
68 return( depth < GCEM_ERF_MAX_ITER ? \
69 // if
70 x + 2 * depth / erf_cf_large_recur(x,depth+1) :
71 // else
72 x );
73}
74
75#endif
76
77template<typename T>
78constexpr
79T
81noexcept
82{
83 return( T(1) - T(2) * ( exp(-x*x) / T(GCEM_SQRT_PI) ) \
84 / erf_cf_large_recur(T(2)*x,1) );
85}
86
87// see
88// http://functions.wolfram.com/GammaBetaErf/Erf/10/01/0005/
89
90#if __cplusplus >= 201402L // C++14 version
91
92template<typename T>
93constexpr
94T
95erf_cf_small_recur(const T xx, const int depth_end)
96noexcept
97{
98 int depth = GCEM_ERF_MAX_ITER - 1;
99 T res = T(2*(depth+1) - 1) - 2 * xx;
100
101 while (depth > depth_end - 1) {
102 res = T(2*depth - 1) - 2 * xx + 4 * depth * xx / res;
103
104 --depth;
105 }
106
107 return res;
108}
109
110#else // C++11 version
111
112template<typename T>
113constexpr
114T
115erf_cf_small_recur(const T xx, const int depth)
116noexcept
117{
118 return( depth < GCEM_ERF_MAX_ITER ? \
119 // if
120 (2*depth - T(1)) - 2 * xx \
121 + 4 * depth * xx / erf_cf_small_recur(xx,depth+1) :
122 // else
123 (2*depth - T(1)) - 2*xx );
124}
125
126#endif
127
128template<typename T>
129constexpr
130T
132noexcept
133{
134 return( T(2) * x * ( exp(-x*x) / T(GCEM_SQRT_PI) ) \
135 / erf_cf_small_recur(x*x,1) );
136}
137
138//
139
140template<typename T>
141constexpr
142T
143erf_begin(const T x)
144noexcept
145{
146 return( x > T(2.1) ? \
147 // if
149 // else
151}
152
153template<typename T>
154constexpr
155T
156erf_check(const T x)
157noexcept
158{
159 return( // NaN check
160 is_nan(x) ? \
162 // +/-Inf
163 is_posinf(x) ? \
164 T(1) :
165 is_neginf(x) ? \
166 - T(1) :
167 // indistinguishable from zero
168 GCLIM<T>::min() > abs(x) ? \
169 T(0) :
170 // else
171 x < T(0) ? \
172 - erf_begin(-x) :
173 erf_begin( x) );
174}
175
176}
177
178/**
179 * Compile-time Gaussian error function
180 *
181 * @param x a real-valued input.
182 * @return computes the Gaussian error function
183 * \f[ \text{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x \exp( - t^2) dt \f]
184 * using a continued fraction representation:
185 * \f[ \text{erf}(x) = \frac{2x}{\sqrt{\pi}} \exp(-x^2) \dfrac{1}{1 - 2x^2 + \dfrac{4x^2}{3 - 2x^2 + \dfrac{8x^2}{5 - 2x^2 + \dfrac{12x^2}{7 - 2x^2 + \ddots}}}} \f]
186 */
187
188template<typename T>
189constexpr
191erf(const T x)
192noexcept
193{
194 if (std::is_constant_evaluated()) {
195 return internal::erf_check( static_cast<return_t<T>>(x) );
196 } else {
197 return std::erf(x);
198 }
199}
200
201}
202
203#endif
#define GCEM_SQRT_PI
Definition gcem_options.hpp:122
#define GCEM_ERF_MAX_ITER
Definition gcem_options.hpp:137
constexpr T erf_cf_small_recur(const T xx, const int depth) noexcept
Definition erf.hpp:115
constexpr T erf_cf_small_main(const T x) noexcept
Definition erf.hpp:131
constexpr bool is_nan(const T x) noexcept
Definition is_nan.hpp:39
constexpr T erf_begin(const T x) noexcept
Definition erf.hpp:143
constexpr bool is_posinf(const T x) noexcept
Definition is_inf.hpp:84
constexpr T erf_cf_large_recur(const T x, const int depth) noexcept
Definition erf.hpp:65
constexpr T erf_cf_large_main(const T x) noexcept
Definition erf.hpp:80
constexpr bool is_neginf(const T x) noexcept
Definition is_inf.hpp:37
constexpr T erf_check(const T x) noexcept
Definition erf.hpp:156
Definition is_odd.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition abs.hpp:40
constexpr return_t< T > erf(const T x) noexcept
Compile-time Gaussian error function.
Definition erf.hpp:191
std::numeric_limits< T > GCLIM
Definition gcem_options.hpp:74
typename std::conditional< std::is_integral< T >::value, double, T >::type return_t
Definition gcem_options.hpp:77