1const HYP_EPM1_O_THRESHOLD: f64 = asdouble(0x40862E42FEFA39EF);
15const HYP_EPM1_LN2_HI: f64 = asdouble(0x3FE62E42FEE00000);
16const HYP_EPM1_LN2_LO: f64 = asdouble(0x3DEA39EF35793C76);
17const HYP_EPM1_INVLN2: f64 = asdouble(0x3FF71547652B82FE);
18const HYP_EPM1_Q1: f64 = asdouble(0xBFA11111111110F4);
19const HYP_EPM1_Q2: f64 = asdouble(0x3F5A01A019FE5585);
20const HYP_EPM1_Q3: f64 = asdouble(0xBF14CE199EAADBB7);
21const HYP_EPM1_Q4: f64 = asdouble(0x3ED0CFCA86E65239);
22const HYP_EPM1_Q5: f64 = asdouble(0xBE8AFDB76E09C32D);
23
24const HYP_EPM1F_LN2_HI: f32 = asfloat(0x3F317180);
29const HYP_EPM1F_LN2_LO: f32 = asfloat(0x3717F7D1);
30const HYP_EPM1F_INVLN2: f32 = asfloat(0x3FB8AA3B);
31const HYP_EPM1F_Q1: f32 = asfloat(0xBD088868);
32const HYP_EPM1F_Q2: f32 = asfloat(0x3ACF3010);
33
34const HYP_EXPO2_KLN2: f64 = asdouble(0x40962066151ADD8B);
39const HYP_EXPO2_SCALE: f64 = asdouble(0x7FC0000000000000);
40
41const HYP_EXPO2F_KLN2: f32 = asfloat(0x4322E3BC);
42const HYP_EXPO2F_SCALE: f32 = asfloat(0x7A000000);
43
44const HYP_TWO120: f64 = asdouble(0x4770000000000000);
46const HYP_TWO1023: f64 = asdouble(0x7FE0000000000000);
48const HYP_TWO127F: f32 = asfloat(0x7F000000);
50
51#[inline]
56fn hyper_expo2(x: f64, sign: f64) -> f64 {
57 let scale = HYP_EXPO2_SCALE;
58 exp(x - HYP_EXPO2_KLN2) * (sign * scale) * scale
59}
60
61#[inline]
66fn hyper_expo2f(x: f32, sign: f32) -> f32 {
67 let scale = HYP_EXPO2F_SCALE;
68 expf(x - HYP_EXPO2F_KLN2) * (sign * scale) * scale
69}
70
71#[inline]
76fn hyper_expm1(x: f64) -> f64 {
77 let u = asuint64(x);
78 let hx = ((u >> 32) & 0x7fffffff) as u32;
79 let sign = (u >> 63) as i32;
80
81 let mut x = x;
83 if hx >= 0x4043687A {
84 if x.is_nan() {
85 return x;
86 }
87 if sign != 0 {
88 return -1.0;
89 }
90 if x > HYP_EPM1_O_THRESHOLD {
91 x *= HYP_TWO1023;
92 return x;
93 }
94 }
95
96 let k: i32;
97 let hi: f64;
98 let lo: f64;
99 let c: f64;
100
101 if hx > 0x3fd62e42 {
103 if hx < 0x3FF0A2B2 {
104 if sign == 0 {
105 hi = x - HYP_EPM1_LN2_HI;
106 lo = HYP_EPM1_LN2_LO;
107 k = 1;
108 } else {
109 hi = x + HYP_EPM1_LN2_HI;
110 lo = -HYP_EPM1_LN2_LO;
111 k = -1;
112 }
113 } else {
114 let kt = if sign == 0 {
115 HYP_EPM1_INVLN2 * x + 0.5
116 } else {
117 HYP_EPM1_INVLN2 * x - 0.5
118 };
119 k = kt as i32;
120 let t = k as f64;
121 hi = x - t * HYP_EPM1_LN2_HI;
122 lo = t * HYP_EPM1_LN2_LO;
123 }
124 x = hi - lo;
125 c = (hi - x) - lo;
126 } else if hx < 0x3c900000 {
127 if hx < 0x00100000 {
129 force_eval(x as f32);
130 }
131 return x;
132 } else {
133 k = 0;
134 c = 0.0; }
136
137 let hfx = 0.5 * x;
139 let hxs = x * hfx;
140 let r1 = 1.0 + hxs * (HYP_EPM1_Q1 + hxs * (HYP_EPM1_Q2 + hxs * (HYP_EPM1_Q3 + hxs * (HYP_EPM1_Q4 + hxs * HYP_EPM1_Q5))));
141 let t = 3.0 - r1 * hfx;
142 let e = hxs * ((r1 - t) / (6.0 - x * t));
143 if k == 0 {
144 return x - (x * e - hxs);
146 }
147 let e = x * (e - c) - c;
148 let e = e - hxs;
149 if k == -1 {
151 return 0.5 * (x - e) - 0.5;
152 }
153 if k == 1 {
154 if x < -0.25 {
155 return -2.0 * (e - (x + 0.5));
156 }
157 return 1.0 + 2.0 * (x - e);
158 }
159 let twopk = asdouble(((0x3ff_i64 + k as i64) as u64) << 52);
160 if k < 0 || k > 56 {
161 let mut y = x - e + 1.0;
163 if k == 1024 {
164 y = y * 2.0 * HYP_TWO1023;
165 } else {
166 y = y * twopk;
167 }
168 return y - 1.0;
169 }
170 let neg_twopk = asdouble(((0x3ff_i64 - k as i64) as u64) << 52);
171 if k < 20 {
172 (x - e + (1.0 - neg_twopk)) * twopk
173 } else {
174 (x - (e + neg_twopk) + 1.0) * twopk
175 }
176}
177
178#[inline]
183fn hyper_expm1f(x: f32) -> f32 {
184 let u = asuint(x);
185 let hx = u & 0x7fffffff;
186 let sign = (u >> 31) as i32;
187
188 let mut x = x;
190 if hx >= 0x4195b844 {
191 if hx > 0x7f800000 {
192 return x;
194 }
195 if sign != 0 {
196 return -1.0;
197 }
198 if hx > 0x42b17217 {
199 x *= HYP_TWO127F;
201 return x;
202 }
203 }
204
205 let k: i32;
206 let hi: f32;
207 let lo: f32;
208 let c: f32;
209
210 if hx > 0x3eb17218 {
212 if hx < 0x3F851592 {
213 if sign == 0 {
214 hi = x - HYP_EPM1F_LN2_HI;
215 lo = HYP_EPM1F_LN2_LO;
216 k = 1;
217 } else {
218 hi = x + HYP_EPM1F_LN2_HI;
219 lo = -HYP_EPM1F_LN2_LO;
220 k = -1;
221 }
222 } else {
223 let kt = if sign == 0 {
224 HYP_EPM1F_INVLN2 * x + 0.5
225 } else {
226 HYP_EPM1F_INVLN2 * x - 0.5
227 };
228 k = kt as i32;
229 let t = k as f32;
230 hi = x - t * HYP_EPM1F_LN2_HI;
231 lo = t * HYP_EPM1F_LN2_LO;
232 }
233 x = hi - lo;
234 c = (hi - x) - lo;
235 } else if hx < 0x33000000 {
236 if hx < 0x00800000 {
238 force_eval(x * x);
239 }
240 return x;
241 } else {
242 k = 0;
243 c = 0.0;
244 }
245
246 let hfx = 0.5 * x;
248 let hxs = x * hfx;
249 let r1 = 1.0 + hxs * (HYP_EPM1F_Q1 + hxs * HYP_EPM1F_Q2);
250 let t = 3.0 - r1 * hfx;
251 let e = hxs * ((r1 - t) / (6.0 - x * t));
252 if k == 0 {
253 return x - (x * e - hxs);
255 }
256 let e = x * (e - c) - c;
257 let e = e - hxs;
258 if k == -1 {
260 return 0.5 * (x - e) - 0.5;
261 }
262 if k == 1 {
263 if x < -0.25 {
264 return -2.0 * (e - (x + 0.5));
265 }
266 return 1.0 + 2.0 * (x - e);
267 }
268 let twopk = asfloat(((0x7f + k) as u32) << 23);
269 if k < 0 || k > 56 {
270 let mut y = x - e + 1.0;
272 if k == 128 {
273 y = y * 2.0 * HYP_TWO127F;
274 } else {
275 y = y * twopk;
276 }
277 return y - 1.0;
278 }
279 let neg_twopk = asfloat(((0x7f - k) as u32) << 23);
280 if k < 23 {
281 (x - e + (1.0 - neg_twopk)) * twopk
282 } else {
283 (x - (e + neg_twopk) + 1.0) * twopk
284 }
285}
286
287#[no_mangle]
292pub extern "C" fn sinh(x: f64) -> f64 {
293 let u = asuint64(x);
294 let mut h = 0.5f64;
295 if u >> 63 != 0 {
296 h = -h;
297 }
298 let u = u & 0x7FFFFFFFFFFFFFFF;
300 let absx = asdouble(u);
301 let w = (u >> 32) as u32;
302
303 if w < 0x40862e42 {
305 let t = hyper_expm1(absx);
306 if w < 0x3ff00000 {
307 if w < 0x3ff00000 - (26 << 20) {
308 return x;
311 }
312 return h * (2.0 * t - t * t / (t + 1.0));
313 }
314 return h * (t + t / (t + 1.0));
316 }
317
318 hyper_expo2(absx, 2.0 * h)
321}
322
323#[no_mangle]
324pub extern "C" fn cosh(x: f64) -> f64 {
325 let u = asuint64(x);
326 let u = u & 0x7FFFFFFFFFFFFFFF;
328 let x = asdouble(u);
329 let w = (u >> 32) as u32;
330
331 if w < 0x3fe62e42 {
333 if w < 0x3ff00000 - (26 << 20) {
334 force_eval(x + HYP_TWO120);
336 return 1.0;
337 }
338 let t = hyper_expm1(x);
339 return 1.0 + t * t / (2.0 * (1.0 + t));
340 }
341
342 if w < 0x40862e42 {
344 let t = exp(x);
345 return 0.5 * (t + 1.0 / t);
347 }
348
349 hyper_expo2(x, 1.0)
352}
353
354#[no_mangle]
355pub extern "C" fn tanh(x: f64) -> f64 {
356 let u = asuint64(x);
357 let sign = (u >> 63) as i32;
358 let u = u & 0x7FFFFFFFFFFFFFFF;
360 let x = asdouble(u);
361 let w = (u >> 32) as u32;
362
363 let t: f64;
364 if w > 0x3fe193ea {
365 if w > 0x40340000 {
367 t = 1.0 - 0.0 / x;
370 } else {
371 let tmp = hyper_expm1(2.0 * x);
372 t = 1.0 - 2.0 / (tmp + 2.0);
373 }
374 } else if w > 0x3fd058ae {
375 let tmp = hyper_expm1(2.0 * x);
377 t = tmp / (tmp + 2.0);
378 } else if w >= 0x00100000 {
379 let tmp = hyper_expm1(-2.0 * x);
381 t = -tmp / (tmp + 2.0);
382 } else {
383 force_eval(x as f32);
386 t = x;
387 }
388 if sign != 0 { -t } else { t }
389}
390
391#[no_mangle]
396pub extern "C" fn sinhf(x: f32) -> f32 {
397 let u = asuint(x);
398 let mut h = 0.5f32;
399 if u >> 31 != 0 {
400 h = -h;
401 }
402 let u = u & 0x7fffffff;
404 let absx = asfloat(u);
405 let w = u;
406
407 if w < 0x42b17217 {
409 let t = hyper_expm1f(absx);
410 if w < 0x3f800000 {
411 if w < 0x3f800000 - (12 << 23) {
412 return x;
413 }
414 return h * (2.0 * t - t * t / (t + 1.0));
415 }
416 return h * (t + t / (t + 1.0));
417 }
418
419 hyper_expo2f(absx, 2.0 * h)
421}
422
423#[no_mangle]
424pub extern "C" fn coshf(x: f32) -> f32 {
425 let u = asuint(x);
426 let u = u & 0x7fffffff;
428 let x = asfloat(u);
429 let w = u;
430
431 if w < 0x3f317217 {
433 if w < 0x3f800000 - (12 << 23) {
434 force_eval(x + asfloat(0x7B800000)); return 1.0;
436 }
437 let t = hyper_expm1f(x);
438 return 1.0 + t * t / (2.0 * (1.0 + t));
439 }
440
441 if w < 0x42b17217 {
443 let t = expf(x);
444 return 0.5 * (t + 1.0 / t);
445 }
446
447 hyper_expo2f(x, 1.0)
449}
450
451#[no_mangle]
452pub extern "C" fn tanhf(x: f32) -> f32 {
453 let u = asuint(x);
454 let sign = (u >> 31) as i32;
455 let u = u & 0x7fffffff;
457 let x = asfloat(u);
458 let w = u;
459
460 let t: f32;
461 if w > 0x3f0c9f54 {
462 if w > 0x41200000 {
464 t = 1.0 + 0.0 / x;
466 } else {
467 let tmp = hyper_expm1f(2.0 * x);
468 t = 1.0 - 2.0 / (tmp + 2.0);
469 }
470 } else if w > 0x3e82c578 {
471 let tmp = hyper_expm1f(2.0 * x);
473 t = tmp / (tmp + 2.0);
474 } else if w >= 0x00800000 {
475 let tmp = hyper_expm1f(-2.0 * x);
477 t = -tmp / (tmp + 2.0);
478 } else {
479 force_eval(x * x);
481 t = x;
482 }
483 if sign != 0 { -t } else { t }
484}