@@ -153,7 +153,19 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t)
153
153
if ((boost::math::isnan)(z))
154
154
return policies::raise_domain_error (" boost::math::erf<%1%>(%1%)" , " Expected a finite argument but got %1%" , z, pol);
155
155
156
- if (z < 0 )
156
+ if (fabs (z) < tools::root_epsilon<T>())
157
+ {
158
+ // Series[Erf[x], {x, 0, 4}]
159
+ // Series[Erfc[x], {x, 0, 4}]
160
+
161
+ const T term2 { z * 2 / constants::root_pi<T>() };
162
+
163
+ return invert ? 1 - term2 : term2;
164
+ }
165
+
166
+ const bool signbit_result = ((boost::math::signbit)(z) != 0 );
167
+
168
+ if (signbit_result)
157
169
{
158
170
if (!invert)
159
171
return -erf_imp (T (-z), invert, pol, t);
@@ -172,32 +184,32 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t)
172
184
}
173
185
else
174
186
{
175
- T x = z * z;
187
+ const T z_sq { z * z };
188
+
176
189
if (z < 1 .3f )
177
190
{
178
191
// Compute P:
179
192
// This is actually good for z p to 2 or so, but the cutoff given seems
180
- // to be the best compromise. Performance wise , this is way quicker than anything else...
193
+ // to be the best compromise. Regarding performance , this is way quicker than anything else...
181
194
result = erf_series_near_zero_sum (z, pol);
182
195
}
183
- else if (x > 1 / tools::epsilon<T>())
196
+ else if (z_sq > 1 / tools::epsilon<T>())
184
197
{
185
198
// http://functions.wolfram.com/06.27.06.0006.02
186
199
invert = !invert;
187
- result = exp (-x ) / (constants::root_pi<T>() * z);
200
+ result = exp (-z_sq ) / (constants::root_pi<T>() * z);
188
201
}
189
202
else
190
203
{
191
204
// Compute Q:
192
205
invert = !invert;
193
- result = z * exp (-x );
206
+ result = z * exp (-z_sq );
194
207
result /= boost::math::constants::root_pi<T>();
195
- result *= upper_gamma_fraction (T (0 .5f ), x , policies::get_epsilon<T, Policy>());
208
+ result *= upper_gamma_fraction (T (0 .5f ), z_sq , policies::get_epsilon<T, Policy>());
196
209
}
197
210
}
198
- if (invert)
199
- result = 1 - result;
200
- return result;
211
+
212
+ return ((!invert) ? result : 1 - result);
201
213
}
202
214
// LCOV_EXCL_STOP
203
215
0 commit comments