1use crate::common::f_fmla;
30
31static COEFFS: [[u64; 8]; 32] = [
37 [
38 0x3ff20dd750429b6d,
39 0xbfd812746b037753,
40 0x3fbce2f219e8596a,
41 0xbf9b82cdacb78fda,
42 0x3f756479297dfda5,
43 0xbf48b3ac5455ef02,
44 0xbf7126fcac367e3b,
45 0x3fb2d0bdb3ba4984,
46 ],
47 [
48 0x3ff20dd750429b6d,
49 0xbfd812746b0379a8,
50 0x3fbce2f21a03cf2a,
51 0xbf9b82ce30de083e,
52 0x3f7565bcad3eb60f,
53 0xbf4c02c66f659256,
54 0x3f1f92f673385229,
55 0xbeedef402648ae90,
56 ],
57 [
58 0x3ff20dd750429b34,
59 0xbfd812746b032dce,
60 0x3fbce2f219d84aae,
61 0xbf9b82ce22dcf139,
62 0x3f7565b9efcd4af1,
63 0xbf4c021f1af414bc,
64 0x3f1f7c6d177eff82,
65 0xbeec9e4410dcf865,
66 ],
67 [
68 0x3ff20dd750426eab,
69 0xbfd812746ae592c7,
70 0x3fbce2f211525f14,
71 0xbf9b82ccc125e63f,
72 0x3f756596f261cfd3,
73 0xbf4bfde1ff8eeecf,
74 0x3f1f31a9d15dc5d8,
75 0xbeea5a4362844b3c,
76 ],
77 [
78 0x3ff20dd75039c705,
79 0xbfd812746777e74d,
80 0x3fbce2f17af98a1b,
81 0xbf9b82be4b817cbe,
82 0x3f7564bec2e2962e,
83 0xbf4bee86f9da3558,
84 0x3f1e9443689dc0cc,
85 0xbee79c0f230805d8,
86 ],
87 [
88 0x3ff20dd74f811211,
89 0xbfd81274371a3e8f,
90 0x3fbce2ec038262e5,
91 0xbf9b8265b82c5e1f,
92 0x3f75615a2e239267,
93 0xbf4bc63ae023dceb,
94 0x3f1d87c2102f7e06,
95 0xbee49584bea41d62,
96 ],
97 [
98 0x3ff20dd746d063e3,
99 0xbfd812729a8a950f,
100 0x3fbce2cb0a2df232,
101 0xbf9b80eca1f51278,
102 0x3f75572e26c46815,
103 0xbf4b715e5638b65e,
104 0x3f1bfbb195484968,
105 0xbee177a565c15c52,
106 ],
107 [
108 0x3ff20dd701b44486,
109 0xbfd812691145f237,
110 0x3fbce23a06b8cfd9,
111 0xbf9b7c1dc7245288,
112 0x3f753e92f7f397dd,
113 0xbf4ad97cc4acf0b2,
114 0x3f19f028b2b09b71,
115 0xbedcdc4da08da8c1,
116 ],
117 [
118 0x3ff20dd5715ac332,
119 0xbfd8123e680bd0eb,
120 0x3fbce0457aded691,
121 0xbf9b6f52d52bed40,
122 0x3f750c291b84414c,
123 0xbf49ea246b1ad4a9,
124 0x3f177654674e0ca0,
125 0xbed737c11a1bcebb,
126 ],
127 [
128 0x3ff20dce6593e114,
129 0xbfd811a59c02eadc,
130 0x3fbcdab53c7cd7d5,
131 0xbf9b526d2e321eed,
132 0x3f74b1d32cd8b994,
133 0xbf48963143ec0a1e,
134 0x3f14ad5700e4db91,
135 0xbed231e100e43ef2,
136 ],
137 [
138 0x3ff20db48bfd5a62,
139 0xbfd80fdd84f9e308,
140 0x3fbccd340d462983,
141 0xbf9b196a29287680,
142 0x3f74210c2c13a0f7,
143 0xbf46dbdfb4ff71ae,
144 0x3f11bca2d17fbd71,
145 0xbecbca36f90c7cf5,
146 ],
147 [
148 0x3ff20d64b2f8f508,
149 0xbfd80b4d4f19fa8b,
150 0x3fbcb088197262e3,
151 0xbf9ab51fd02e5b99,
152 0x3f734e1e5e81a632,
153 0xbf44c66377b502ce,
154 0x3f0d9ad25066213c,
155 0xbec4b0df7dd0cfa1,
156 ],
157 [
158 0x3ff20c8fc1243576,
159 0xbfd8010cb2009e27,
160 0x3fbc7a47e9299315,
161 0xbf9a155be5683654,
162 0x3f7233502694997b,
163 0xbf426c94b7d81300,
164 0x3f08094f1de25fb9,
165 0xbebe0e3d776c6eef,
166 ],
167 [
168 0x3ff20a9bd1611bc1,
169 0xbfd7ec7fbce83f90,
170 0x3fbc1d757d7317b7,
171 0xbf992c160cd589f0,
172 0x3f70d307269cc5c2,
173 0xbf3fda5b0d2d1879,
174 0x3f02fdd7b3b14a7f,
175 0xbeb54eed4a26af5a,
176 ],
177 [
178 0x3ff20682834f943d,
179 0xbfd7c73f747bf5a9,
180 0x3fbb8c2db4a9ffd1,
181 0xbf97f0e4ffe989ec,
182 0x3f6e7061eae4166e,
183 0xbf3ad36e873fff2d,
184 0x3efd39222396128e,
185 0xbead83dacec5ea6b,
186 ],
187 [
188 0x3ff1feb8d12676d7,
189 0xbfd7898347284afe,
190 0x3fbaba3466b34451,
191 0xbf9663adc573e2f9,
192 0x3f6ae99fb17c3e08,
193 0xbf3602f950ad5535,
194 0x3ef5e9717490609d,
195 0xbea3fca107bbc8d5,
196 ],
197 [
198 0x3ff1f12fe3c536fa,
199 0xbfd72b1d1f22e6d3,
200 0x3fb99fc0eed4a896,
201 0xbf948db0a87bd8c6,
202 0x3f673e368895aa61,
203 0xbf319b35d5301fc8,
204 0x3ef007987e4bb033,
205 0xbe9a7edcd4c2dc70,
206 ],
207 [
208 0x3ff1db7b0df84d5d,
209 0xbfd6a4e4a41cde02,
210 0x3fb83bbded16455d,
211 0xbf92809b3b36977e,
212 0x3f639c08bab44679,
213 0xbf2b7b45a70ed119,
214 0x3ee6e99b36410e7b,
215 0xbe913619bb7ebc0c,
216 ],
217 [
218 0x3ff1bb1c85c4a527,
219 0xbfd5f23b99a249a3,
220 0x3fb694c91fa0d12c,
221 0xbf9053e1ce11c72d,
222 0x3f602bf72c50ea78,
223 0xbf24f478fb56cb02,
224 0x3ee005f80ecbe213,
225 0xbe85f2446bde7f5b,
226 ],
227 [
228 0x3ff18dec3bd51f9d,
229 0xbfd5123f58346186,
230 0x3fb4b8a1ca536ab4,
231 0xbf8c4243015cc723,
232 0x3f5a1a8a01d351ef,
233 0xbf1f466b34f1d86b,
234 0x3ed5f835eea0bf6a,
235 0xbe7b83165b939234,
236 ],
237 [
238 0x3ff152804c3369f4,
239 0xbfd4084cd4afd4bc,
240 0x3fb2ba2e836e47aa,
241 0xbf8800f2dfc6904b,
242 0x3f54a6daf0669c59,
243 0xbf16e326ab872317,
244 0x3ecd9761a6a755a5,
245 0xbe70fca33f9dd4b5,
246 ],
247 [
248 0x3ff1087ad68356aa,
249 0xbfd2dbb044707459,
250 0x3fb0aea8ceaa0384,
251 0xbf840b516d52b3d2,
252 0x3f500c9e05f01d22,
253 0xbf1076afb0dc0ff7,
254 0x3ec39fadec400657,
255 0xbe64b5761352e7e3,
256 ],
257 [
258 0x3ff0b0a7a8ba4a22,
259 0xbfd196990d22d4a1,
260 0x3fad5551e6ac0c4d,
261 0xbf807cce1770bd1a,
262 0x3f4890347b8848bf,
263 0xbf0757ec96750b6a,
264 0x3eb9b258a1e06bce,
265 0xbe58fc6d22da7572,
266 ],
267 [
268 0x3ff04ce2be70fb47,
269 0xbfd0449e4b0b9cac,
270 0x3fa97f7424f4b0e7,
271 0xbf7ac825439c42f4,
272 0x3f428f5f65426dfb,
273 0xbf005b699a90f90f,
274 0x3eb0a888eecf4593,
275 0xbe4deace2b32bb31,
276 ],
277 [
278 0x3fefbf9fb0e11cc8,
279 0xbfcde2640856545a,
280 0x3fa5f5b1f47f8510,
281 0xbf7588bc71eb41b9,
282 0x3f3bc6a0a772f56d,
283 0xbef6b9fad1f1657a,
284 0x3ea573204ba66504,
285 0xbe41d38065c94e44,
286 ],
287 [
288 0x3feed8f18c99e031,
289 0xbfcb4cb6acd903b4,
290 0x3fa2c7f3dddd6fc1,
291 0xbf713052067df4e0,
292 0x3f34a5027444082f,
293 0xbeef672bab0e2554,
294 0x3e9b83c756348cc9,
295 0xbe3534f1a1079499,
296 ],
297 [
298 0x3fedebd33044166d,
299 0xbfc8d7cd9053f7d8,
300 0x3f9ff9957fb3d6e7,
301 0xbf6b50be55de0f36,
302 0x3f2e92c8ec53a628,
303 0xbee5a4b88d508007,
304 0x3e91a27737559e26,
305 0xbe2942ae62cb2c14,
306 ],
307 [
308 0x3fecfdbf0386f3bd,
309 0xbfc68e33d93b0dc4,
310 0x3f9b2683d58f53de,
311 0xbf65a9174e70d26f,
312 0x3f269ddd326d49cd,
313 0xbeddd8f397a8219c,
314 0x3e86a755016ad4dd,
315 0xbe1e366e0139187d,
316 ],
317 [
318 0x3fec132adb8d7464,
319 0xbfc475a899f61b46,
320 0x3f970a431397a77c,
321 0xbf612e3d35beeee2,
322 0x3f20c16b05738333,
323 0xbed4a47f873e144e,
324 0x3e7d3d494c698c02,
325 0xbe12302c59547fe5,
326 ],
327 [
328 0x3feb2f5fd05555e7,
329 0xbfc28feefbe03ec7,
330 0x3f93923acbb3a676,
331 0xbf5b4ff793cd6358,
332 0x3f18ea0eb8c913bc,
333 0xbeccb31ec2baceb1,
334 0x3e730011e7e80c04,
335 0xbe0617710635cb1d,
336 ],
337 [
338 0x3fea54853cd9593e,
339 0xbfc0dbdbaea4dc8e,
340 0x3f90a93e2c20a0fd,
341 0xbf55c969ff401ea8,
342 0x3f129e0cc64fe627,
343 0xbec4160d8e9d3c2a,
344 0x3e68e7b67594624a,
345 0xbdfb1cf2c975b09b,
346 ],
347 [
348 0x3fe983ceece09ff8,
349 0xbfbeacc78f7a2d00,
350 0x3f8c74418410655f,
351 0xbf51756a050e441e,
352 0x3f0bff3650f7f548,
353 0xbebc56c0217d3ada,
354 0x3e607b4918d0b489,
355 0xbdf0d4be8c1c50f8,
356 ],
357];
358
359#[inline]
363pub fn f_erff(x: f32) -> f32 {
364 let x_u = x.to_bits();
365 let x_abs = x_u & 0x7fff_ffffu32;
366
367 if x_abs >= 0x4080_0000u32 {
368 static ONE: [f32; 2] = [1.0, -1.0];
369 static SMALL: [f32; 2] = [f32::from_bits(0xb3000000), f32::from_bits(0x33000000)];
370
371 let sign = x.is_sign_negative() as usize;
372
373 if x_abs >= 0x7f80_0000u32 {
374 return if x_abs > 0x7f80_0000 { x } else { ONE[sign] };
375 }
376
377 return ONE[sign] + SMALL[sign];
378 }
379
380 let xd = x as f64;
383 let xsq = xd * xd;
384
385 const EIGHT: u32 = 3 << 23;
386 let idx = unsafe { f32::from_bits(x_abs.wrapping_add(EIGHT)).to_int_unchecked::<usize>() };
387
388 let c = COEFFS[idx];
389
390 let x4 = xsq * xsq;
391 let c0 = f_fmla(xsq, f64::from_bits(c[1]), f64::from_bits(c[0]));
392 let c1 = f_fmla(xsq, f64::from_bits(c[3]), f64::from_bits(c[2]));
393 let c2 = f_fmla(xsq, f64::from_bits(c[5]), f64::from_bits(c[4]));
394 let c3 = f_fmla(xsq, f64::from_bits(c[7]), f64::from_bits(c[6]));
395
396 let x8 = x4 * x4;
397 let p0 = f_fmla(x4, c1, c0);
398 let p1 = f_fmla(x4, c3, c2);
399
400 (xd * f_fmla(x8, p1, p0)) as f32
401}
402
403#[cfg(test)]
404mod tests {
405 use super::*;
406
407 #[test]
408 fn f_erff_test() {
409 assert_eq!(f_erff(0.0), 0.0);
410 assert_eq!(f_erff(1.0), 0.8427008);
411 assert_eq!(f_erff(0.5), 0.5204999);
412 assert_eq!(f_erff(f32::INFINITY), 1.0);
413 assert_eq!(f_erff(f32::NEG_INFINITY), -1.0);
414 assert!(f_erff(f32::NAN).is_nan());
415 }
416}