/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.26/src/exponents/expf.rs
Line | Count | Source |
1 | | /* |
2 | | * // Copyright (c) Radzivon Bartoshyk 4/2025. All rights reserved. |
3 | | * // |
4 | | * // Redistribution and use in source and binary forms, with or without modification, |
5 | | * // are permitted provided that the following conditions are met: |
6 | | * // |
7 | | * // 1. Redistributions of source code must retain the above copyright notice, this |
8 | | * // list of conditions and the following disclaimer. |
9 | | * // |
10 | | * // 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | * // this list of conditions and the following disclaimer in the documentation |
12 | | * // and/or other materials provided with the distribution. |
13 | | * // |
14 | | * // 3. Neither the name of the copyright holder nor the names of its |
15 | | * // contributors may be used to endorse or promote products derived from |
16 | | * // this software without specific prior written permission. |
17 | | * // |
18 | | * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
19 | | * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 | | * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
22 | | * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
24 | | * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
25 | | * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
26 | | * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 | | * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | use crate::common::{f_fmla, f_fmlaf, fmlaf, pow2if, rintfk}; |
30 | | use crate::polyeval::f_polyeval5; |
31 | | use crate::rounding::CpuRound; |
32 | | |
33 | | const L2U_F: f32 = 0.693_145_751_953_125; |
34 | | const L2L_F: f32 = 1.428_606_765_330_187_045_e-6; |
35 | | const R_LN2_F: f32 = std::f32::consts::LOG2_E; |
36 | | |
37 | | /// Exp for given value for const context. |
38 | | /// This is simplified version just to make a good approximation on const context. |
39 | | #[inline] |
40 | 0 | pub const fn expf(d: f32) -> f32 { |
41 | | const EXP_POLY_1_S: f32 = 2f32; |
42 | | const EXP_POLY_2_S: f32 = 0.16666707f32; |
43 | | const EXP_POLY_3_S: f32 = -0.002775669f32; |
44 | 0 | let qf = rintfk(d * R_LN2_F); |
45 | 0 | let q = qf as i32; |
46 | 0 | let r = fmlaf(qf, -L2U_F, d); |
47 | 0 | let r = fmlaf(qf, -L2L_F, r); |
48 | | |
49 | 0 | let f = r * r; |
50 | | // Poly for u = r*(exp(r)+1)/(exp(r)-1) |
51 | 0 | let mut u = EXP_POLY_3_S; |
52 | 0 | u = fmlaf(u, f, EXP_POLY_2_S); |
53 | 0 | u = fmlaf(u, f, EXP_POLY_1_S); |
54 | 0 | let u = 1f32 + 2f32 * r / (u - r); |
55 | 0 | let i2 = pow2if(q); |
56 | 0 | u * i2 |
57 | | // if d < -87f32 { |
58 | | // r = 0f32; |
59 | | // } |
60 | | // if d > 88f32 { |
61 | | // r = f32::INFINITY; |
62 | | // } |
63 | 0 | } |
64 | | |
65 | | // Lookup table for exp(m) with m = -104, ..., 102. |
66 | | // -104 = floor(log(single precision's min denormal)) |
67 | | // 103 = ceil(log(single precision's max bessel K(n) that will be used)) |
68 | | // Table is generated with SageMath as follows: |
69 | | // for r in range(-104, 103): |
70 | | // print(double_to_hex(RealField(180)(r).exp()) + ",") |
71 | | pub(crate) static EXP_M1: [u64; 207] = [ |
72 | | 0x368f1e6b68529e33, |
73 | | 0x36a525be4e4e601d, |
74 | | 0x36bcbe0a45f75eb1, |
75 | | 0x36d3884e838aea68, |
76 | | 0x36ea8c1f14e2af5d, |
77 | | 0x37020a717e64a9bd, |
78 | | 0x3718851d84118908, |
79 | | 0x3730a9bdfb02d240, |
80 | | 0x3746a5bea046b42e, |
81 | | 0x375ec7f3b269efa8, |
82 | | 0x3774eafb87eab0f2, |
83 | | 0x378c6e2d05bbc000, |
84 | | 0x37a35208867c2683, |
85 | | 0x37ba425b317eeacd, |
86 | | 0x37d1d8508fa8246a, |
87 | | 0x37e840fbc08fdc8a, |
88 | | 0x38007b7112bc1ffe, |
89 | | 0x381666d0dad2961d, |
90 | | 0x382e726c3f64d0fe, |
91 | | 0x3844b0dc07cabf98, |
92 | | 0x385c1f2daf3b6a46, |
93 | | 0x38731c5957a47de2, |
94 | | 0x3889f96445648b9f, |
95 | | 0x38a1a6baeadb4fd1, |
96 | | 0x38b7fd974d372e45, |
97 | | 0x38d04da4d1452919, |
98 | | 0x38e62891f06b3450, |
99 | | 0x38fe1dd273aa8a4a, |
100 | | 0x3914775e0840bfdd, |
101 | | 0x392bd109d9d94bda, |
102 | | 0x3942e73f53fba844, |
103 | | 0x3959b138170d6bfe, |
104 | | 0x397175af0cf60ec5, |
105 | | 0x3987baee1bffa80b, |
106 | | 0x39a02057d1245ceb, |
107 | | 0x39b5eafffb34ba31, |
108 | | 0x39cdca23bae16424, |
109 | | 0x39e43e7fc88b8056, |
110 | | 0x39fb83bf23a9a9eb, |
111 | | 0x3a12b2b8dd05b318, |
112 | | 0x3a2969d47321e4cc, |
113 | | 0x3a41452b7723aed2, |
114 | | 0x3a5778fe2497184c, |
115 | | 0x3a6fe7116182e9cc, |
116 | | 0x3a85ae191a99585a, |
117 | | 0x3a9d775d87da854d, |
118 | | 0x3ab4063f8cc8bb98, |
119 | | 0x3acb374b315f87c1, |
120 | | 0x3ae27ec458c65e3c, |
121 | | 0x3af923372c67a074, |
122 | | 0x3b11152eaeb73c08, |
123 | | 0x3b2737c5645114b5, |
124 | | 0x3b3f8e6c24b5592e, |
125 | | 0x3b5571db733a9d61, |
126 | | 0x3b6d257d547e083f, |
127 | | 0x3b83ce9b9de78f85, |
128 | | 0x3b9aebabae3a41b5, |
129 | | 0x3bb24b6031b49bda, |
130 | | 0x3bc8dd5e1bb09d7e, |
131 | | 0x3be0e5b73d1ff53d, |
132 | | 0x3bf6f741de1748ec, |
133 | | 0x3c0f36bd37f42f3e, |
134 | | 0x3c2536452ee2f75c, |
135 | | 0x3c3cd480a1b74820, |
136 | | 0x3c539792499b1a24, |
137 | | 0x3c6aa0de4bf35b38, |
138 | | 0x3c82188ad6ae3303, |
139 | | 0x3c9898471fca6055, |
140 | | 0x3cb0b6c3afdde064, |
141 | | 0x3cc6b7719a59f0e0, |
142 | | 0x3cdee001eed62aa0, |
143 | | 0x3cf4fb547c775da8, |
144 | | 0x3d0c8464f7616468, |
145 | | 0x3d236121e24d3bba, |
146 | | 0x3d3a56e0c2ac7f75, |
147 | | 0x3d51e642baeb84a0, |
148 | | 0x3d6853f01d6d53ba, |
149 | | 0x3d80885298767e9a, |
150 | | 0x3d967852a7007e42, |
151 | | 0x3dae8a37a45fc32e, |
152 | | 0x3dc4c1078fe9228a, |
153 | | 0x3ddc3527e433fab1, |
154 | | 0x3df32b48bf117da2, |
155 | | 0x3e0a0db0d0ddb3ec, |
156 | | 0x3e21b48655f37267, |
157 | | 0x3e381056ff2c5772, |
158 | | 0x3e505a628c699fa1, |
159 | | 0x3e6639e3175a689d, |
160 | | 0x3e7e355bbaee85cb, |
161 | | 0x3e94875ca227ec38, |
162 | | 0x3eabe6c6fdb01612, |
163 | | 0x3ec2f6053b981d98, |
164 | | 0x3ed9c54c3b43bc8b, |
165 | | 0x3ef18354238f6764, |
166 | | 0x3f07cd79b5647c9b, |
167 | | 0x3f202cf22526545a, |
168 | | 0x3f35fc21041027ad, |
169 | | 0x3f4de16b9c24a98f, |
170 | | 0x3f644e51f113d4d6, |
171 | | 0x3f7b993fe00d5376, |
172 | | 0x3f92c155b8213cf4, |
173 | | 0x3fa97db0ccceb0af, |
174 | | 0x3fc152aaa3bf81cc, |
175 | | 0x3fd78b56362cef38, |
176 | | 0x3ff0000000000000, |
177 | | 0x4005bf0a8b145769, |
178 | | 0x401d8e64b8d4ddae, |
179 | | 0x403415e5bf6fb106, |
180 | | 0x404b4c902e273a58, |
181 | | 0x40628d389970338f, |
182 | | 0x407936dc5690c08f, |
183 | | 0x409122885aaeddaa, |
184 | | 0x40a749ea7d470c6e, |
185 | | 0x40bfa7157c470f82, |
186 | | 0x40d5829dcf950560, |
187 | | 0x40ed3c4488ee4f7f, |
188 | | 0x4103de1654d37c9a, |
189 | | 0x411b00b5916ac955, |
190 | | 0x413259ac48bf05d7, |
191 | | 0x4148f0ccafad2a87, |
192 | | 0x4160f2ebd0a80020, |
193 | | 0x417709348c0ea4f9, |
194 | | 0x418f4f22091940bd, |
195 | | 0x41a546d8f9ed26e1, |
196 | | 0x41bceb088b68e804, |
197 | | 0x41d3a6e1fd9eecfd, |
198 | | 0x41eab5adb9c43600, |
199 | | 0x420226af33b1fdc1, |
200 | | 0x4218ab7fb5475fb7, |
201 | | 0x4230c3d3920962c9, |
202 | | 0x4246c932696a6b5d, |
203 | | 0x425ef822f7f6731d, |
204 | | 0x42750bba3796379a, |
205 | | 0x428c9aae4631c056, |
206 | | 0x42a370470aec28ed, |
207 | | 0x42ba6b765d8cdf6d, |
208 | | 0x42d1f43fcc4b662c, |
209 | | 0x42e866f34a725782, |
210 | | 0x4300953e2f3a1ef7, |
211 | | 0x431689e221bc8d5b, |
212 | | 0x432ea215a1d20d76, |
213 | | 0x4344d13fbb1a001a, |
214 | | 0x435c4b334617cc67, |
215 | | 0x43733a43d282a519, |
216 | | 0x438a220d397972eb, |
217 | | 0x43a1c25c88df6862, |
218 | | 0x43b8232558201159, |
219 | | 0x43d0672a3c9eb871, |
220 | | 0x43e64b41c6d37832, |
221 | | 0x43fe4cf766fe49be, |
222 | | 0x44149767bc0483e3, |
223 | | 0x442bfc951eb8bb76, |
224 | | 0x444304d6aeca254b, |
225 | | 0x4459d97010884251, |
226 | | 0x44719103e4080b45, |
227 | | 0x4487e013cd114461, |
228 | | 0x44a03996528e074c, |
229 | | 0x44b60d4f6fdac731, |
230 | | 0x44cdf8c5af17ba3b, |
231 | | 0x44e45e3076d61699, |
232 | | 0x44fbaed16a6e0da7, |
233 | | 0x4512cffdfebde1a1, |
234 | | 0x4529919cabefcb69, |
235 | | 0x454160345c9953e3, |
236 | | 0x45579dbc9dc53c66, |
237 | | 0x45700c810d464097, |
238 | | 0x4585d009394c5c27, |
239 | | 0x459da57de8f107a8, |
240 | | 0x45b425982cf597cd, |
241 | | 0x45cb61e5ca3a5e31, |
242 | | 0x45e29bb825dfcf87, |
243 | | 0x45f94a90db0d6fe2, |
244 | | 0x46112fec759586fd, |
245 | | 0x46275c1dc469e3af, |
246 | | 0x463fbfd219c43b04, |
247 | | 0x4655936d44e1a146, |
248 | | 0x466d531d8a7ee79c, |
249 | | 0x4683ed9d24a2d51b, |
250 | | 0x469b15cfe5b6e17b, |
251 | | 0x46b268038c2c0e00, |
252 | | 0x46c9044a73545d48, |
253 | | 0x46e1002ab6218b38, |
254 | | 0x46f71b3540cbf921, |
255 | | 0x470f6799ea9c414a, |
256 | | 0x47255779b984f3eb, |
257 | | 0x473d01a210c44aa4, |
258 | | 0x4753b63da8e91210, |
259 | | 0x476aca8d6b0116b8, |
260 | | 0x478234de9e0c74e9, |
261 | | 0x4798bec7503ca477, |
262 | | 0x47b0d0eda9796b90, |
263 | | 0x47c6db0118477245, |
264 | | 0x47df1056dc7bf22d, |
265 | | 0x47f51c2cc3433801, |
266 | | 0x480cb108ffbec164, |
267 | | 0x48237f780991b584, |
268 | | 0x483a801c0ea8ac4d, |
269 | | 0x48520247cc4c46c1, |
270 | | 0x48687a0553328015, |
271 | | 0x4880a233dee4f9bb, |
272 | | 0x48969b7f55b808ba, |
273 | | 0x48aeba064644060a, |
274 | | 0x48c4e184933d9364, |
275 | | 0x48dc614fe2531841, |
276 | | 0x48f3494a9b171bf5, |
277 | | 0x490a36798b9d969b, |
278 | | 0x4921d03d8c0c04af, |
279 | | ]; |
280 | | |
281 | | // Lookup table for exp(m * 2^(-7)) with m = 0, ..., 127. |
282 | | // Table is generated with Sollya as follows: |
283 | | // > display = hexadecimal; |
284 | | // > for i from 0 to 127 do { D(exp(i / 128)); }; |
285 | | pub(crate) static EXP_M2: [u64; 128] = [ |
286 | | 0x3ff0000000000000, |
287 | | 0x3ff0202015600446, |
288 | | 0x3ff04080ab55de39, |
289 | | 0x3ff06122436410dd, |
290 | | 0x3ff08205601127ed, |
291 | | 0x3ff0a32a84e9c1f6, |
292 | | 0x3ff0c49236829e8c, |
293 | | 0x3ff0e63cfa7ab09d, |
294 | | 0x3ff1082b577d34ed, |
295 | | 0x3ff12a5dd543ccc5, |
296 | | 0x3ff14cd4fc989cd6, |
297 | | 0x3ff16f9157587069, |
298 | | 0x3ff192937074e0cd, |
299 | | 0x3ff1b5dbd3f68122, |
300 | | 0x3ff1d96b0eff0e79, |
301 | | 0x3ff1fd41afcba45e, |
302 | | 0x3ff2216045b6f5cd, |
303 | | 0x3ff245c7613b8a9b, |
304 | | 0x3ff26a7793f60164, |
305 | | 0x3ff28f7170a755fd, |
306 | | 0x3ff2b4b58b372c79, |
307 | | 0x3ff2da4478b620c7, |
308 | | 0x3ff3001ecf601af7, |
309 | | 0x3ff32645269ea829, |
310 | | 0x3ff34cb8170b5835, |
311 | | 0x3ff373783a722012, |
312 | | 0x3ff39a862bd3c106, |
313 | | 0x3ff3c1e2876834aa, |
314 | | 0x3ff3e98deaa11dcc, |
315 | | 0x3ff41188f42c3e32, |
316 | | 0x3ff439d443f5f159, |
317 | | 0x3ff462707b2bac21, |
318 | | 0x3ff48b5e3c3e8186, |
319 | | 0x3ff4b49e2ae5ac67, |
320 | | 0x3ff4de30ec211e60, |
321 | | 0x3ff50817263c13cd, |
322 | | 0x3ff5325180cfacf7, |
323 | | 0x3ff55ce0a4c58c7c, |
324 | | 0x3ff587c53c5a7af0, |
325 | | 0x3ff5b2fff3210fd9, |
326 | | 0x3ff5de9176045ff5, |
327 | | 0x3ff60a7a734ab0e8, |
328 | | 0x3ff636bb9a983258, |
329 | | 0x3ff663559cf1bc7c, |
330 | | 0x3ff690492cbf9433, |
331 | | 0x3ff6bd96fdd034a2, |
332 | | 0x3ff6eb3fc55b1e76, |
333 | | 0x3ff719443a03acb9, |
334 | | 0x3ff747a513dbef6a, |
335 | | 0x3ff776630c678bc1, |
336 | | 0x3ff7a57ede9ea23e, |
337 | | 0x3ff7d4f946f0ba8d, |
338 | | 0x3ff804d30347b546, |
339 | | 0x3ff8350cd30ac390, |
340 | | 0x3ff865a7772164c5, |
341 | | 0x3ff896a3b1f66a0e, |
342 | | 0x3ff8c802477b0010, |
343 | | 0x3ff8f9c3fd29beaf, |
344 | | 0x3ff92be99a09bf00, |
345 | | 0x3ff95e73e6b1b75e, |
346 | | 0x3ff99163ad4b1dcc, |
347 | | 0x3ff9c4b9b995509b, |
348 | | 0x3ff9f876d8e8c566, |
349 | | 0x3ffa2c9bda3a3e78, |
350 | | 0x3ffa61298e1e069c, |
351 | | 0x3ffa9620c6cb3374, |
352 | | 0x3ffacb82581eee54, |
353 | | 0x3ffb014f179fc3b8, |
354 | | 0x3ffb3787dc80f95f, |
355 | | 0x3ffb6e2d7fa5eb18, |
356 | | 0x3ffba540dba56e56, |
357 | | 0x3ffbdcc2cccd3c85, |
358 | | 0x3ffc14b431256446, |
359 | | 0x3ffc4d15e873c193, |
360 | | 0x3ffc85e8d43f7cd0, |
361 | | 0x3ffcbf2dd7d490f2, |
362 | | 0x3ffcf8e5d84758a9, |
363 | | 0x3ffd3311bc7822b4, |
364 | | 0x3ffd6db26d16cd67, |
365 | | 0x3ffda8c8d4a66969, |
366 | | 0x3ffde455df80e3c0, |
367 | | 0x3ffe205a7bdab73e, |
368 | | 0x3ffe5cd799c6a54e, |
369 | | 0x3ffe99ce2b397649, |
370 | | 0x3ffed73f240dc142, |
371 | | 0x3fff152b7a07bb76, |
372 | | 0x3fff539424d90f5e, |
373 | | 0x3fff927a1e24bb76, |
374 | | 0x3fffd1de6182f8c9, |
375 | | 0x400008e0f64294ab, |
376 | | 0x40002912df5ce72a, |
377 | | 0x400049856cd84339, |
378 | | 0x40006a39207f0a09, |
379 | | 0x40008b2e7d2035cf, |
380 | | 0x4000ac6606916501, |
381 | | 0x4000cde041b0e9ae, |
382 | | 0x4000ef9db467dcf8, |
383 | | 0x4001119ee5ac36b6, |
384 | | 0x400133e45d82e952, |
385 | | 0x4001566ea50201d7, |
386 | | 0x4001793e4652cc50, |
387 | | 0x40019c53ccb3fc6b, |
388 | | 0x4001bfafc47bda73, |
389 | | 0x4001e352bb1a74ad, |
390 | | 0x4002073d3f1bd518, |
391 | | 0x40022b6fe02a3b9c, |
392 | | 0x40024feb2f105cb8, |
393 | | 0x400274afbdbba4a6, |
394 | | 0x400299be1f3e7f1c, |
395 | | 0x4002bf16e7d2a38c, |
396 | | 0x4002e4baacdb6614, |
397 | | 0x40030aaa04e80d05, |
398 | | 0x400330e587b62b28, |
399 | | 0x4003576dce33fead, |
400 | | 0x40037e437282d4ee, |
401 | | 0x4003a5670ff972ed, |
402 | | 0x4003ccd9432682b4, |
403 | | 0x4003f49aa9d30590, |
404 | | 0x40041cabe304cb34, |
405 | | 0x4004450d8f00edd4, |
406 | | 0x40046dc04f4e5338, |
407 | | 0x400496c4c6b832da, |
408 | | 0x4004c01b9950a111, |
409 | | 0x4004e9c56c731f5d, |
410 | | 0x400513c2e6c731d7, |
411 | | 0x40053e14b042f9ca, |
412 | | 0x400568bb722dd593, |
413 | | 0x400593b7d72305bb, |
414 | | ]; |
415 | | |
416 | | /// Computes exp |
417 | | /// |
418 | | /// Max found ULP 0.5 |
419 | | #[inline] |
420 | 0 | pub fn f_expf(x: f32) -> f32 { |
421 | 0 | let x_u = x.to_bits(); |
422 | 0 | let x_abs = x_u & 0x7fff_ffffu32; |
423 | 0 | if x_abs >= 0x42b2_0000u32 || x_abs <= 0x3280_0000u32 { |
424 | 0 | let exp = ((x_u >> 23) & 0xFF) as i32; |
425 | | // |x| < 2^-25 |
426 | 0 | if exp <= 101i32 { |
427 | 0 | return 1.0 + x; |
428 | 0 | } |
429 | | |
430 | | // When x < log(2^-150) or nan |
431 | 0 | if x_u >= 0xc2cf_f1b5u32 { |
432 | | // exp(-Inf) = 0 |
433 | 0 | if x.is_infinite() { |
434 | 0 | return 0.0; |
435 | 0 | } |
436 | | // exp(nan) = nan |
437 | 0 | if x.is_nan() { |
438 | 0 | return x; |
439 | 0 | } |
440 | 0 | return 0.0; |
441 | 0 | } |
442 | | // x >= 89 or nan |
443 | 0 | if x.is_sign_positive() && (x_u >= 0x42b2_0000) { |
444 | | // x is +inf or nan |
445 | 0 | return x + f32::INFINITY; |
446 | 0 | } |
447 | 0 | } |
448 | | |
449 | | // For -104 < x < 89, to compute exp(x), we perform the following range |
450 | | // reduction: find hi, mid, lo such that: |
451 | | // x = hi + mid + lo, in which |
452 | | // hi is an integer, |
453 | | // mid * 2^7 is an integer |
454 | | // -2^(-8) <= lo < 2^-8. |
455 | | // In particular, |
456 | | // hi + mid = round(x * 2^7) * 2^(-7). |
457 | | // Then, |
458 | | // exp(x) = exp(hi + mid + lo) = exp(hi) * exp(mid) * exp(lo). |
459 | | // We store exp(hi) and exp(mid) in the lookup tables EXP_M1 and EXP_M2 |
460 | | // respectively. exp(lo) is computed using a degree-4 minimax polynomial |
461 | | // generated by Sollya. |
462 | | |
463 | | // x_hi = (hi + mid) * 2^7 = round(x * 2^7). |
464 | 0 | let kf = (x * 128.).cpu_round(); |
465 | | // Subtract (hi + mid) from x to get lo. |
466 | 0 | let xd = f_fmlaf(kf, -0.0078125 /* - 1/128 */, x) as f64; |
467 | 0 | let mut x_hi = unsafe { kf.to_int_unchecked::<i32>() }; // it's already not indeterminate. |
468 | 0 | x_hi += 104 << 7; |
469 | | // hi = x_hi >> 7 |
470 | 0 | let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); |
471 | | // mid * 2^7 = x_hi & 0x0000'007fU; |
472 | 0 | let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); |
473 | | // Degree-4 minimax polynomial generated by Sollya with the following |
474 | | // commands: |
475 | | // d = [-2^-8, 2^-8]; |
476 | | // f_exp = expm1(x)/x; |
477 | | // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); |
478 | 0 | let p = f_polyeval5( |
479 | 0 | xd, |
480 | | 1., |
481 | 0 | f64::from_bits(0x3feffffffffff777), |
482 | 0 | f64::from_bits(0x3fe000000000071c), |
483 | 0 | f64::from_bits(0x3fc555566668e5e7), |
484 | 0 | f64::from_bits(0x3fa55555555ef243), |
485 | | ); |
486 | 0 | (p * exp_hi * exp_mid) as f32 |
487 | 0 | } Unexecuted instantiation: pxfm::exponents::expf::f_expf Unexecuted instantiation: pxfm::exponents::expf::f_expf |
488 | | |
489 | | #[inline] |
490 | 0 | pub(crate) fn core_expf(x: f32) -> f64 { |
491 | | // x_hi = (hi + mid) * 2^7 = round(x * 2^7). |
492 | 0 | let kf = (x * 128.).cpu_round(); |
493 | | // Subtract (hi + mid) from x to get lo. |
494 | 0 | let xd = f_fmlaf(kf, -0.0078125 /* - 1/128 */, x) as f64; |
495 | 0 | let mut x_hi = unsafe { kf.to_int_unchecked::<i32>() }; // it's already not indeterminate. |
496 | 0 | x_hi += 104 << 7; |
497 | | // hi = x_hi >> 7 |
498 | 0 | let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); |
499 | | // mid * 2^7 = x_hi & 0x0000'007fU; |
500 | 0 | let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); |
501 | | // Degree-4 minimax polynomial generated by Sollya with the following |
502 | | // commands: |
503 | | // d = [-2^-8, 2^-8]; |
504 | | // f_exp = expm1(x)/x; |
505 | | // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); |
506 | 0 | let p = f_polyeval5( |
507 | 0 | xd, |
508 | | 1., |
509 | 0 | f64::from_bits(0x3feffffffffff777), |
510 | 0 | f64::from_bits(0x3fe000000000071c), |
511 | 0 | f64::from_bits(0x3fc555566668e5e7), |
512 | 0 | f64::from_bits(0x3fa55555555ef243), |
513 | | ); |
514 | 0 | p * exp_hi * exp_mid |
515 | 0 | } |
516 | | |
517 | | #[inline] |
518 | 0 | pub(crate) fn core_expdf(x: f64) -> f64 { |
519 | | // x_hi = (hi + mid) * 2^7 = round(x * 2^7). |
520 | 0 | let kf = (x * 128.).cpu_round(); |
521 | | // Subtract (hi + mid) from x to get lo. |
522 | 0 | let xd = f_fmla(kf, -0.0078125 /* - 1/128 */, x); |
523 | 0 | let mut x_hi = unsafe { kf.to_int_unchecked::<i32>() }; // it's already not indeterminate. |
524 | 0 | x_hi += 104 << 7; |
525 | | // hi = x_hi >> 7 |
526 | 0 | let exp_hi = f64::from_bits(EXP_M1[(x_hi >> 7) as usize]); |
527 | | // mid * 2^7 = x_hi & 0x0000'007fU; |
528 | 0 | let exp_mid = f64::from_bits(EXP_M2[(x_hi & 0x7f) as usize]); |
529 | | // Degree-4 minimax polynomial generated by Sollya with the following |
530 | | // commands: |
531 | | // d = [-2^-8, 2^-8]; |
532 | | // f_exp = expm1(x)/x; |
533 | | // Q = fpminimax(f_exp, 3, [|D...|], [-2^-8, 2^-8]); |
534 | 0 | let p = f_polyeval5( |
535 | 0 | xd, |
536 | | 1., |
537 | 0 | f64::from_bits(0x3feffffffffff777), |
538 | 0 | f64::from_bits(0x3fe000000000071c), |
539 | 0 | f64::from_bits(0x3fc555566668e5e7), |
540 | 0 | f64::from_bits(0x3fa55555555ef243), |
541 | | ); |
542 | 0 | p * exp_hi * exp_mid |
543 | 0 | } |
544 | | |
545 | | #[cfg(test)] |
546 | | mod tests { |
547 | | use super::*; |
548 | | |
549 | | #[test] |
550 | | fn expf_test() { |
551 | | assert!( |
552 | | (expf(0f32) - 1f32).abs() < 1e-6, |
553 | | "Invalid result {}", |
554 | | expf(0f32) |
555 | | ); |
556 | | assert!( |
557 | | (expf(5f32) - 148.4131591025766f32).abs() < 1e-6, |
558 | | "Invalid result {}", |
559 | | expf(5f32) |
560 | | ); |
561 | | } |
562 | | |
563 | | #[test] |
564 | | fn f_expf_test() { |
565 | | assert_eq!(f_expf(-103.971596), 1e-45); |
566 | | assert!( |
567 | | (f_expf(0f32) - 1f32).abs() < 1e-6, |
568 | | "Invalid result {}", |
569 | | f_expf(0f32) |
570 | | ); |
571 | | assert!( |
572 | | (f_expf(5f32) - 148.4131591025766f32).abs() < 1e-6, |
573 | | "Invalid result {}", |
574 | | f_expf(5f32) |
575 | | ); |
576 | | assert_eq!(f_expf(f32::INFINITY), f32::INFINITY); |
577 | | assert_eq!(f_expf(f32::NEG_INFINITY), 0.); |
578 | | assert!(f_expf(f32::NAN).is_nan()); |
579 | | } |
580 | | } |