1use crate::bessel::alpha1::{
30 bessel_1_asympt_alpha, bessel_1_asympt_alpha_fast, bessel_1_asympt_alpha_hard,
31};
32use crate::bessel::beta1::{
33 bessel_1_asympt_beta, bessel_1_asympt_beta_fast, bessel_1_asympt_beta_hard,
34};
35use crate::bessel::i0::bessel_rsqrt_hard;
36use crate::bessel::y1_coeffs::Y1_COEFFS_REMEZ;
37use crate::bessel::y1_coeffs_taylor::Y1_COEFFS;
38use crate::bessel::y1f_coeffs::{Y1_ZEROS, Y1_ZEROS_VALUES};
39use crate::common::f_fmla;
40use crate::double_double::DoubleDouble;
41use crate::dyadic_float::{DyadicFloat128, DyadicSign};
42use crate::logs::log_dd_fast;
43use crate::polyeval::{f_polyeval12, f_polyeval13, f_polyeval15, f_polyeval22, f_polyeval24};
44use crate::rounding::CpuCeil;
45use crate::sin_helper::{cos_dd_small, cos_dd_small_fast, cos_f128_small};
46use crate::sincos_reduce::{AngleReduced, rem2pi_any, rem2pi_f128};
47
48pub fn f_y1(x: f64) -> f64 {
50 let ix = x.to_bits();
51
52 if ix >= 0x7ffu64 << 52 || ix == 0 {
53 if ix.wrapping_shl(1) == 0 {
55 return f64::NEG_INFINITY;
57 }
58
59 if x.is_infinite() {
60 if x.is_sign_negative() {
61 return f64::NAN;
62 }
63 return 0.;
64 }
65
66 return x + f64::NAN; }
68
69 let xb = x.to_bits();
70
71 if xb <= 0x4049c00000000000u64 {
72 if xb <= 0x4000000000000000u64 {
74 if xb <= 0x3ff75c28f5c28f5cu64 {
76 return y1_near_zero_fast(x);
78 }
79 return y1_transient_zone_fast(x);
82 }
83
84 return y1_small_argument_fast(x);
85 }
86
87 y1_asympt_fast(x)
88}
89
90#[inline]
132fn y1_near_zero_fast(x: f64) -> f64 {
133 const W: [(u64, u64); 15] = [
134 (0xbc76b01ec5417056, 0x3fd45f306dc9c883),
135 (0x3c46b01ec5417056, 0xbfa45f306dc9c883),
136 (0xbbfe40290701eb1e, 0x3f5b2995e7b7b604),
137 (0xbba67fe4a5feb897, 0xbf021bb945252402),
138 (0xbb0334914cdd2ba9, 0x3e9cf9286ea1d337),
139 (0x3aab4f3c6d42c1f4, 0xbe2ee7a29824147f),
140 (0xba407fb57ef4dc2c, 0x3db78be9987d036d),
141 (0x39d2921e91b07dd0, 0xbd3ae90af76a4d0f),
142 (0x395a28c8620dc90e, 0x3cb7eb97f85e7d62),
143 (0xb8cf83f52abe45c5, 0xbc31028e3376648a),
144 (0xb8441050c68ca435, 0x3ba3cb1e7d0c17e7),
145 (0xb7ab072548a1aa43, 0xbb133191ed9f1eef),
146 (0xb6f05192c2d9b6ee, 0x3a7f7f4b5e8ef7b0),
147 (0x367ad65afe306d57, 0xb9e626e36cb3515d),
148 (0xb5ea1c4136f8f230, 0x394b01153dce6810),
149 ];
150 let x2 = DoubleDouble::from_exact_mult(x, x);
151 let w0 = f_polyeval12(
152 x2.hi,
153 f64::from_bits(W[3].1),
154 f64::from_bits(W[4].1),
155 f64::from_bits(W[5].1),
156 f64::from_bits(W[6].1),
157 f64::from_bits(W[7].1),
158 f64::from_bits(W[8].1),
159 f64::from_bits(W[9].1),
160 f64::from_bits(W[10].1),
161 f64::from_bits(W[11].1),
162 f64::from_bits(W[12].1),
163 f64::from_bits(W[13].1),
164 f64::from_bits(W[14].1),
165 );
166
167 let mut w = DoubleDouble::mul_f64_add(x2, w0, DoubleDouble::from_bit_pair(W[2]));
168 w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[1]));
169 w = DoubleDouble::mul_add(x2, w, DoubleDouble::from_bit_pair(W[0]));
170 w = DoubleDouble::quick_mult_f64(w, x);
171
172 const Z: [(u64, u64); 15] = [
173 (0x3c61d7eb2e54cda1, 0x3fc91866143cbc8a),
174 (0xbc2f9f7a0ce54a40, 0xbfabd3975c75b4a7),
175 (0xbbf7659313f45e8c, 0x3f6835b97894be5b),
176 (0x3b9cbcd40f1be7b9, 0xbf12c7dbffcde97d),
177 (0xbb495d78778645b4, 0x3eb0a780ac776eac),
178 (0xbae15be86455c1ab, 0xbe432e5a4ddeea30),
179 (0xba5ad966c12f1e3c, 0x3dcf0ce34d2066a6),
180 (0x39e9717155dc7521, 0xbd52a4e1aea45c18),
181 (0x394f447fe5de1290, 0x3cd1474ade9154ac),
182 (0xb8e1699d9009a7fc, 0xbc4978ba84f218c0),
183 (0xb8505502096ead17, 0x3bbe9598c016378b),
184 (0x37942b6c36b2c5f1, 0xbb2e7e5fcfc4b7b1),
185 (0x37210853b78bd08a, 0x3a99a6c1266c116d),
186 (0xb686c9639c9d976e, 0xba02738998fe7337),
187 (0xb603b739ee04b9fe, 0x3966f58cd41b6d08),
188 ];
189 let z0 = f_polyeval12(
190 x2.hi,
191 f64::from_bits(Z[3].1),
192 f64::from_bits(Z[4].1),
193 f64::from_bits(Z[5].1),
194 f64::from_bits(Z[6].1),
195 f64::from_bits(Z[7].1),
196 f64::from_bits(Z[8].1),
197 f64::from_bits(Z[9].1),
198 f64::from_bits(Z[10].1),
199 f64::from_bits(Z[11].1),
200 f64::from_bits(Z[12].1),
201 f64::from_bits(Z[13].1),
202 f64::from_bits(Z[14].1),
203 );
204
205 let mut z = DoubleDouble::mul_f64_add(x2, z0, DoubleDouble::from_bit_pair(Z[2]));
206 z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[1]));
207 z = DoubleDouble::mul_add(x2, z, DoubleDouble::from_bit_pair(Z[0]));
208 z = DoubleDouble::quick_mult_f64(z, x);
209
210 let w_log = log_dd_fast(x);
211
212 const MINUS_TWO_OVER_PI: DoubleDouble =
213 DoubleDouble::from_bit_pair((0x3c86b01ec5417056, 0xbfe45f306dc9c883));
214
215 let m_two_over_pi_div_x: DoubleDouble;
216 #[cfg(any(
217 all(
218 any(target_arch = "x86", target_arch = "x86_64"),
219 target_feature = "fma"
220 ),
221 target_arch = "aarch64"
222 ))]
223 {
224 m_two_over_pi_div_x = DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x)
225 }
226 #[cfg(not(any(
227 all(
228 any(target_arch = "x86", target_arch = "x86_64"),
229 target_feature = "fma"
230 ),
231 target_arch = "aarch64"
232 )))]
233 {
234 use crate::double_double::two_product_compatible;
235 m_two_over_pi_div_x = if two_product_compatible(x) {
236 DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x)
237 } else {
238 DoubleDouble::div_safe_dd_f64(MINUS_TWO_OVER_PI, x)
239 };
240 }
241 if m_two_over_pi_div_x.hi.is_infinite() {
242 return f64::NEG_INFINITY;
243 }
244
245 let zvp = DoubleDouble::mul_add(w, w_log, -z);
246 let p = DoubleDouble::add(m_two_over_pi_div_x, zvp);
247 let err = f_fmla(
248 p.hi,
249 f64::from_bits(0x3c30000000000000), f64::from_bits(0x3be0000000000000), );
252 let ub = p.hi + (p.lo + err);
253 let lb = p.hi + (p.lo - err);
254 if ub == lb {
255 return p.to_f64();
256 }
257 y1_near_zero(x, w_log)
258}
259
260#[cold]
302#[inline(never)]
303fn y1_near_zero(x: f64, w_log: DoubleDouble) -> f64 {
304 const W: [(u64, u64); 15] = [
305 (0xbc76b01ec5417056, 0x3fd45f306dc9c883),
306 (0x3c46b01ec5417056, 0xbfa45f306dc9c883),
307 (0xbbfe40290701eb1e, 0x3f5b2995e7b7b604),
308 (0xbba67fe4a5feb897, 0xbf021bb945252402),
309 (0xbb0334914cdd2ba9, 0x3e9cf9286ea1d337),
310 (0x3aab4f3c6d42c1f4, 0xbe2ee7a29824147f),
311 (0xba407fb57ef4dc2c, 0x3db78be9987d036d),
312 (0x39d2921e91b07dd0, 0xbd3ae90af76a4d0f),
313 (0x395a28c8620dc90e, 0x3cb7eb97f85e7d62),
314 (0xb8cf83f52abe45c5, 0xbc31028e3376648a),
315 (0xb8441050c68ca435, 0x3ba3cb1e7d0c17e7),
316 (0xb7ab072548a1aa43, 0xbb133191ed9f1eef),
317 (0xb6f05192c2d9b6ee, 0x3a7f7f4b5e8ef7b0),
318 (0x367ad65afe306d57, 0xb9e626e36cb3515d),
319 (0xb5ea1c4136f8f230, 0x394b01153dce6810),
320 ];
321 let x2 = DoubleDouble::from_exact_mult(x, x);
322 let mut w = f_polyeval15(
323 x2,
324 DoubleDouble::from_bit_pair(W[0]),
325 DoubleDouble::from_bit_pair(W[1]),
326 DoubleDouble::from_bit_pair(W[2]),
327 DoubleDouble::from_bit_pair(W[3]),
328 DoubleDouble::from_bit_pair(W[4]),
329 DoubleDouble::from_bit_pair(W[5]),
330 DoubleDouble::from_bit_pair(W[6]),
331 DoubleDouble::from_bit_pair(W[7]),
332 DoubleDouble::from_bit_pair(W[8]),
333 DoubleDouble::from_bit_pair(W[9]),
334 DoubleDouble::from_bit_pair(W[10]),
335 DoubleDouble::from_bit_pair(W[11]),
336 DoubleDouble::from_bit_pair(W[12]),
337 DoubleDouble::from_bit_pair(W[13]),
338 DoubleDouble::from_bit_pair(W[14]),
339 );
340 w = DoubleDouble::quick_mult_f64(w, x);
341
342 const Z: [(u64, u64); 15] = [
343 (0x3c61d7eb2e54cda1, 0x3fc91866143cbc8a),
344 (0xbc2f9f7a0ce54a40, 0xbfabd3975c75b4a7),
345 (0xbbf7659313f45e8c, 0x3f6835b97894be5b),
346 (0x3b9cbcd40f1be7b9, 0xbf12c7dbffcde97d),
347 (0xbb495d78778645b4, 0x3eb0a780ac776eac),
348 (0xbae15be86455c1ab, 0xbe432e5a4ddeea30),
349 (0xba5ad966c12f1e3c, 0x3dcf0ce34d2066a6),
350 (0x39e9717155dc7521, 0xbd52a4e1aea45c18),
351 (0x394f447fe5de1290, 0x3cd1474ade9154ac),
352 (0xb8e1699d9009a7fc, 0xbc4978ba84f218c0),
353 (0xb8505502096ead17, 0x3bbe9598c016378b),
354 (0x37942b6c36b2c5f1, 0xbb2e7e5fcfc4b7b1),
355 (0x37210853b78bd08a, 0x3a99a6c1266c116d),
356 (0xb686c9639c9d976e, 0xba02738998fe7337),
357 (0xb603b739ee04b9fe, 0x3966f58cd41b6d08),
358 ];
359 let mut z = f_polyeval15(
360 x2,
361 DoubleDouble::from_bit_pair(Z[0]),
362 DoubleDouble::from_bit_pair(Z[1]),
363 DoubleDouble::from_bit_pair(Z[2]),
364 DoubleDouble::from_bit_pair(Z[3]),
365 DoubleDouble::from_bit_pair(Z[4]),
366 DoubleDouble::from_bit_pair(Z[5]),
367 DoubleDouble::from_bit_pair(Z[6]),
368 DoubleDouble::from_bit_pair(Z[7]),
369 DoubleDouble::from_bit_pair(Z[8]),
370 DoubleDouble::from_bit_pair(Z[9]),
371 DoubleDouble::from_bit_pair(Z[10]),
372 DoubleDouble::from_bit_pair(Z[11]),
373 DoubleDouble::from_bit_pair(Z[12]),
374 DoubleDouble::from_bit_pair(Z[13]),
375 DoubleDouble::from_bit_pair(Z[14]),
376 );
377 z = DoubleDouble::quick_mult_f64(z, x);
378
379 const MINUS_TWO_OVER_PI: DoubleDouble =
380 DoubleDouble::from_bit_pair((0x3c86b01ec5417056, 0xbfe45f306dc9c883));
381
382 let m_two_over_pi_div_x: DoubleDouble;
383 #[cfg(any(
384 all(
385 any(target_arch = "x86", target_arch = "x86_64"),
386 target_feature = "fma"
387 ),
388 target_arch = "aarch64"
389 ))]
390 {
391 m_two_over_pi_div_x = DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x)
392 }
393 #[cfg(not(any(
394 all(
395 any(target_arch = "x86", target_arch = "x86_64"),
396 target_feature = "fma"
397 ),
398 target_arch = "aarch64"
399 )))]
400 {
401 use crate::double_double::two_product_compatible;
402 m_two_over_pi_div_x = if two_product_compatible(x) {
403 DoubleDouble::div_dd_f64(MINUS_TWO_OVER_PI, x)
404 } else {
405 DoubleDouble::div_safe_dd_f64(MINUS_TWO_OVER_PI, x)
406 };
407 }
408 if m_two_over_pi_div_x.hi.is_infinite() {
409 return f64::NEG_INFINITY;
410 }
411
412 let zvp = DoubleDouble::mul_add(w, w_log, -z);
413 DoubleDouble::full_dd_add(m_two_over_pi_div_x, zvp).to_f64()
414}
415
416#[inline]
417fn y1_transient_zone_fast(x: f64) -> f64 {
418 const C: [(u64, u64); 28] = [
428 (0x38d23216c8eac2ee, 0x3c631de77e55e9b0),
429 (0x3c77f3a6718f8e03, 0x3fe0aa48442f0150),
430 (0xbc52b77d09be8679, 0xbfbe56f82217b33a),
431 (0x3c237af39fc9d759, 0xbfa0d2af4e922afe),
432 (0xbc08241e95389bc3, 0xbf73a6dec2f9f739),
433 (0x3c18eac6a35acd63, 0x3f7e671c82a1c956),
434 (0x3be0a0f3c8908083, 0xbf65429d5dbc3bb0),
435 (0x3be217fa58861600, 0x3f517abad71c26c0),
436 (0x3bebc327d6c65514, 0xbf40b28b4ef33a56),
437 (0xbbcb597d6bdd5992, 0x3f2ef0d150ec9934),
438 (0x3bb1a480de696e07, 0xbf1c0758a86844be),
439 (0xbb9c6ea6352ab84e, 0x3f0b7c88b58d9ef3),
440 (0x3b7dbb78dfd868a9, 0xbee97ef9519bdcfd),
441 (0xbb8d4519030f499d, 0x3f04815f08e7ad5e),
442 (0x3bbbd70e1480e260, 0x3f10f348483b57bc),
443 (0x3b7117cf4d2b6f3c, 0x3f231914389bb1bb),
444 (0x3b8ca48beaf6a58d, 0x3f30b29e838345b4),
445 (0x3bccfac65ce17cf9, 0x3f39a69e98f61897),
446 (0xbbeae7e3065b09c9, 0x3f40b9511666fcf0),
447 (0xbbe5cbddf691e7e6, 0x3f428cd8388e634b),
448 (0xbbd91372412d1e1b, 0x3f414ba048d9e1d5),
449 (0xbbb0781a70c6f715, 0x3f3acdcf66f1de95),
450 (0xbba3ae83fd425494, 0x3f30f44ae6620bba),
451 (0x3bc001d75da77b74, 0x3f21154a0a1f2161),
452 (0xbb91c9afb1a1b874, 0x3f0a687b664cbac6),
453 (0x3b8e0a06b9444963, 0x3eed7c3cbb4ba5d8),
454 (0x3b4f0e9dfc915934, 0x3ec53ca23fdd0999),
455 (0xbb0409258f8ffca8, 0x3e8de620acb51b2d),
456 ];
457
458 const ZERO: DoubleDouble =
460 DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243));
461
462 let mut r = DoubleDouble::full_add_f64(-ZERO, x);
463 r = DoubleDouble::from_exact_add(r.hi, r.lo);
464
465 let p0 = f_polyeval24(
466 r.to_f64(),
467 f64::from_bits(C[4].1),
468 f64::from_bits(C[5].1),
469 f64::from_bits(C[6].1),
470 f64::from_bits(C[7].1),
471 f64::from_bits(C[8].1),
472 f64::from_bits(C[9].1),
473 f64::from_bits(C[10].1),
474 f64::from_bits(C[11].1),
475 f64::from_bits(C[12].1),
476 f64::from_bits(C[13].1),
477 f64::from_bits(C[14].1),
478 f64::from_bits(C[15].1),
479 f64::from_bits(C[16].1),
480 f64::from_bits(C[17].1),
481 f64::from_bits(C[18].1),
482 f64::from_bits(C[19].1),
483 f64::from_bits(C[20].1),
484 f64::from_bits(C[21].1),
485 f64::from_bits(C[22].1),
486 f64::from_bits(C[23].1),
487 f64::from_bits(C[24].1),
488 f64::from_bits(C[25].1),
489 f64::from_bits(C[26].1),
490 f64::from_bits(C[27].1),
491 );
492
493 let mut p = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[3]));
494 p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[2]));
495 p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[1]));
496 p = DoubleDouble::mul_add(p, r, DoubleDouble::from_bit_pair(C[0]));
497
498 let err = f_fmla(
499 p.hi,
500 f64::from_bits(0x3c50000000000000), f64::from_bits(0x3b90000000000000), );
503 let ub = p.hi + (p.lo + err);
504 let lb = p.hi + (p.lo - err);
505 if ub == lb {
506 return p.to_f64();
507 }
508 y1_transient_zone(x)
509}
510
511fn y1_transient_zone(x: f64) -> f64 {
512 const C: [(u64, u64); 28] = [
522 (0x38d23216c8eac2ee, 0x3c631de77e55e9b0),
523 (0x3c77f3a6718f8e03, 0x3fe0aa48442f0150),
524 (0xbc52b77d09be8679, 0xbfbe56f82217b33a),
525 (0x3c237af39fc9d759, 0xbfa0d2af4e922afe),
526 (0xbc08241e95389bc3, 0xbf73a6dec2f9f739),
527 (0x3c18eac6a35acd63, 0x3f7e671c82a1c956),
528 (0x3be0a0f3c8908083, 0xbf65429d5dbc3bb0),
529 (0x3be217fa58861600, 0x3f517abad71c26c0),
530 (0x3bebc327d6c65514, 0xbf40b28b4ef33a56),
531 (0xbbcb597d6bdd5992, 0x3f2ef0d150ec9934),
532 (0x3bb1a480de696e07, 0xbf1c0758a86844be),
533 (0xbb9c6ea6352ab84e, 0x3f0b7c88b58d9ef3),
534 (0x3b7dbb78dfd868a9, 0xbee97ef9519bdcfd),
535 (0xbb8d4519030f499d, 0x3f04815f08e7ad5e),
536 (0x3bbbd70e1480e260, 0x3f10f348483b57bc),
537 (0x3b7117cf4d2b6f3c, 0x3f231914389bb1bb),
538 (0x3b8ca48beaf6a58d, 0x3f30b29e838345b4),
539 (0x3bccfac65ce17cf9, 0x3f39a69e98f61897),
540 (0xbbeae7e3065b09c9, 0x3f40b9511666fcf0),
541 (0xbbe5cbddf691e7e6, 0x3f428cd8388e634b),
542 (0xbbd91372412d1e1b, 0x3f414ba048d9e1d5),
543 (0xbbb0781a70c6f715, 0x3f3acdcf66f1de95),
544 (0xbba3ae83fd425494, 0x3f30f44ae6620bba),
545 (0x3bc001d75da77b74, 0x3f21154a0a1f2161),
546 (0xbb91c9afb1a1b874, 0x3f0a687b664cbac6),
547 (0x3b8e0a06b9444963, 0x3eed7c3cbb4ba5d8),
548 (0x3b4f0e9dfc915934, 0x3ec53ca23fdd0999),
549 (0xbb0409258f8ffca8, 0x3e8de620acb51b2d),
550 ];
551
552 const ZERO: DoubleDouble =
554 DoubleDouble::from_bit_pair((0xbc8bd1e50d219bfd, 0x400193bed4dff243));
555
556 let r = DoubleDouble::full_add_f64(-ZERO, x);
557
558 let p0 = f_polyeval13(
559 r.to_f64(),
560 f64::from_bits(C[15].1),
561 f64::from_bits(C[16].1),
562 f64::from_bits(C[17].1),
563 f64::from_bits(C[18].1),
564 f64::from_bits(C[19].1),
565 f64::from_bits(C[20].1),
566 f64::from_bits(C[21].1),
567 f64::from_bits(C[22].1),
568 f64::from_bits(C[23].1),
569 f64::from_bits(C[24].1),
570 f64::from_bits(C[25].1),
571 f64::from_bits(C[26].1),
572 f64::from_bits(C[27].1),
573 );
574
575 let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(C[14]));
576 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[13]));
577 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[12]));
578 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[11]));
579 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[10]));
580 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[9]));
581 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[8]));
582 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[7]));
583 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[6]));
584 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[5]));
585 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[4]));
586 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[3]));
587 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[2]));
588 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[1]));
589 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(C[0]));
590
591 let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo);
592 let err = f_fmla(
593 p.hi,
594 f64::from_bits(0x3c20000000000000), f64::from_bits(0x3a90000000000000), );
597 let ub = p.hi + (p.lo + err);
598 let lb = p.hi + (p.lo - err);
599 if ub == lb {
600 return p.to_f64();
601 }
602 y1_transient_hard(x)
603}
604
605#[cold]
606#[inline(never)]
607fn y1_transient_hard(x: f64) -> f64 {
608 pub(crate) static C: [DyadicFloat128; 28] = [
618 DyadicFloat128 {
619 sign: DyadicSign::Pos,
620 exponent: -184,
621 mantissa: 0x98ef3bf2_af4d8048_c85b23ab_0bb72488_u128,
622 },
623 DyadicFloat128 {
624 sign: DyadicSign::Pos,
625 exponent: -128,
626 mantissa: 0x85524221_780a817f_3a6718f8_e03513ec_u128,
627 },
628 DyadicFloat128 {
629 sign: DyadicSign::Neg,
630 exponent: -131,
631 mantissa: 0xf2b7c110_bd99d256_efa137d0_cf1f7988_u128,
632 },
633 DyadicFloat128 {
634 sign: DyadicSign::Neg,
635 exponent: -132,
636 mantissa: 0x86957a74_9157ef64_286301b1_453792e2_u128,
637 },
638 DyadicFloat128 {
639 sign: DyadicSign::Neg,
640 exponent: -135,
641 mantissa: 0x9d36f617_cfb9c982_41e95389_bc32e8c2_u128,
642 },
643 DyadicFloat128 {
644 sign: DyadicSign::Pos,
645 exponent: -135,
646 mantissa: 0xf338e415_0e4ab31d_58d46b59_ac6792eb_u128,
647 },
648 DyadicFloat128 {
649 sign: DyadicSign::Neg,
650 exponent: -136,
651 mantissa: 0xaa14eaed_e1dd7f7a_f861bb7b_fbe6acb5_u128,
652 },
653 DyadicFloat128 {
654 sign: DyadicSign::Pos,
655 exponent: -137,
656 mantissa: 0x8bd5d6b8_e1360121_7fa58861_5ff9b614_u128,
657 },
658 DyadicFloat128 {
659 sign: DyadicSign::Neg,
660 exponent: -138,
661 mantissa: 0x85945a77_99d2ac87_9b052735_5d7f5f59_u128,
662 },
663 DyadicFloat128 {
664 sign: DyadicSign::Pos,
665 exponent: -140,
666 mantissa: 0xf7868a87_64c99c94_d0528454_cdccd44c_u128,
667 },
668 DyadicFloat128 {
669 sign: DyadicSign::Neg,
670 exponent: -141,
671 mantissa: 0xe03ac543_4225edcb_6fe432d2_3f11a8b0_u128,
672 },
673 DyadicFloat128 {
674 sign: DyadicSign::Pos,
675 exponent: -142,
676 mantissa: 0xdbe445ac_6cf79639_159cad54_7b1eda7c_u128,
677 },
678 DyadicFloat128 {
679 sign: DyadicSign::Neg,
680 exponent: -144,
681 mantissa: 0xcbf7ca8c_dee7e624_48720279_75757a17_u128,
682 },
683 DyadicFloat128 {
684 sign: DyadicSign::Pos,
685 exponent: -142,
686 mantissa: 0xa40af847_3d6aef15_d737e785_b3163322_u128,
687 },
688 DyadicFloat128 {
689 sign: DyadicSign::Pos,
690 exponent: -141,
691 mantissa: 0x879a4241_dabde37a_e1c2901c_4c06b1dc_u128,
692 },
693 DyadicFloat128 {
694 sign: DyadicSign::Pos,
695 exponent: -140,
696 mantissa: 0x98c8a1c4_dd8dd811_17cf4d2b_6f3c3910_u128,
697 },
698 DyadicFloat128 {
699 sign: DyadicSign::Pos,
700 exponent: -139,
701 mantissa: 0x8594f41c_1a2da01c_a48beaf6_a58cef9f_u128,
702 },
703 DyadicFloat128 {
704 sign: DyadicSign::Pos,
705 exponent: -139,
706 mantissa: 0xcd34f4c7_b0c4b9cf_ac65ce17_cf940c9c_u128,
707 },
708 DyadicFloat128 {
709 sign: DyadicSign::Pos,
710 exponent: -138,
711 mantissa: 0x85ca88b3_37e77ca3_039f349e_c6ddb06d_u128,
712 },
713 DyadicFloat128 {
714 sign: DyadicSign::Pos,
715 exponent: -138,
716 mantissa: 0x9466c1c4_731a5546_84412dc3_033a8ee7_u128,
717 },
718 DyadicFloat128 {
719 sign: DyadicSign::Pos,
720 exponent: -138,
721 mantissa: 0x8a5d0246_cf0ea66e_c8dbed2e_1e50b14f_u128,
722 },
723 DyadicFloat128 {
724 sign: DyadicSign::Pos,
725 exponent: -139,
726 mantissa: 0xd66e7b37_8ef4a77c_3f2c79c8_4757a40d_u128,
727 },
728 DyadicFloat128 {
729 sign: DyadicSign::Pos,
730 exponent: -139,
731 mantissa: 0x87a25733_105dcfb1_45f00af6_adb11b5f_u128,
732 },
733 DyadicFloat128 {
734 sign: DyadicSign::Pos,
735 exponent: -140,
736 mantissa: 0x88aa5050_f90b0a00_3aebb4ef_6e7e9ce1_u128,
737 },
738 DyadicFloat128 {
739 sign: DyadicSign::Pos,
740 exponent: -142,
741 mantissa: 0xd343db32_65d62ee3_6504e5e4_78c55965_u128,
742 },
743 DyadicFloat128 {
744 sign: DyadicSign::Pos,
745 exponent: -144,
746 mantissa: 0xebe1e5da_5d2ec3c1_40d72889_2c57e483_u128,
747 },
748 DyadicFloat128 {
749 sign: DyadicSign::Pos,
750 exponent: -146,
751 mantissa: 0xa9e511fe_e84cc8f8_74efe48a_c9a09ebc_u128,
752 },
753 DyadicFloat128 {
754 sign: DyadicSign::Pos,
755 exponent: -150,
756 mantissa: 0xef310565_a8d9675f_b6d38380_1abf92a6_u128,
757 },
758 ];
759 const ZERO: DyadicFloat128 = DyadicFloat128 {
760 sign: DyadicSign::Pos,
761 exponent: -126,
762 mantissa: 0x8c9df6a6_ff921721_70d796f3_2017e155_u128,
763 };
764 let r = DyadicFloat128::new_from_f64(x) - ZERO;
765
766 let mut p = C[27];
767 for i in (0..27).rev() {
768 p = r * p + C[i];
769 }
770 p.fast_as_f64()
771}
772
773#[inline]
776pub(crate) fn y1_small_argument_fast(x: f64) -> f64 {
777 const INV_STEP: f64 = 0.6466784244562023;
783
784 let fx = x * INV_STEP;
785 const Y1_ZEROS_COUNT: f64 = (Y1_ZEROS.len() - 1) as f64;
786 let idx0 = unsafe { fx.min(Y1_ZEROS_COUNT).to_int_unchecked::<usize>() };
787 let idx1 = unsafe {
788 fx.cpu_ceil()
789 .min(Y1_ZEROS_COUNT)
790 .to_int_unchecked::<usize>()
791 };
792
793 let found_zero0 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx0]);
794 let found_zero1 = DoubleDouble::from_bit_pair(Y1_ZEROS[idx1]);
795
796 let dist0 = (found_zero0.hi - x).abs();
797 let dist1 = (found_zero1.hi - x).abs();
798
799 let (found_zero, idx, dist) = if dist0 < dist1 {
800 (found_zero0, idx0, dist0)
801 } else {
802 (found_zero1, idx1, dist1)
803 };
804
805 if idx == 0 {
806 return y1_near_zero_fast(x);
807 }
808
809 let close_to_zero = dist.abs() < 1e-3;
810
811 let c = if close_to_zero {
812 &Y1_COEFFS[idx - 1]
813 } else {
814 &Y1_COEFFS_REMEZ[idx - 1]
815 };
816
817 let r = DoubleDouble::full_add_f64(-found_zero, x);
818
819 if dist == 0. {
821 return f64::from_bits(Y1_ZEROS_VALUES[idx]);
822 }
823
824 let p = f_polyeval22(
825 r.hi,
826 f64::from_bits(c[6].1),
827 f64::from_bits(c[7].1),
828 f64::from_bits(c[8].1),
829 f64::from_bits(c[9].1),
830 f64::from_bits(c[10].1),
831 f64::from_bits(c[11].1),
832 f64::from_bits(c[12].1),
833 f64::from_bits(c[13].1),
834 f64::from_bits(c[14].1),
835 f64::from_bits(c[15].1),
836 f64::from_bits(c[16].1),
837 f64::from_bits(c[17].1),
838 f64::from_bits(c[18].1),
839 f64::from_bits(c[19].1),
840 f64::from_bits(c[20].1),
841 f64::from_bits(c[21].1),
842 f64::from_bits(c[22].1),
843 f64::from_bits(c[23].1),
844 f64::from_bits(c[24].1),
845 f64::from_bits(c[25].1),
846 f64::from_bits(c[26].1),
847 f64::from_bits(c[27].1),
848 );
849
850 let mut z = DoubleDouble::mul_f64_add(r, p, DoubleDouble::from_bit_pair(c[5]));
851 z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[4]));
852 z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[3]));
853 z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[2]));
854 z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[1]));
855 z = DoubleDouble::mul_add(z, r, DoubleDouble::from_bit_pair(c[0]));
856 let p = z;
857 let err = f_fmla(
858 p.hi,
859 f64::from_bits(0x3c60000000000000), f64::from_bits(0x3c20000000000000), );
862 let ub = p.hi + (p.lo + err);
863 let lb = p.hi + (p.lo - err);
864 if ub == lb {
865 return p.to_f64();
866 }
867 y0_small_argument_moderate(r, c)
868}
869
870fn y0_small_argument_moderate(r: DoubleDouble, c0: &[(u64, u64); 28]) -> f64 {
871 let c = &c0[15..];
872
873 let p0 = f_polyeval13(
874 r.to_f64(),
875 f64::from_bits(c[0].1),
876 f64::from_bits(c[1].1),
877 f64::from_bits(c[2].1),
878 f64::from_bits(c[3].1),
879 f64::from_bits(c[4].1),
880 f64::from_bits(c[5].1),
881 f64::from_bits(c[6].1),
882 f64::from_bits(c[7].1),
883 f64::from_bits(c[8].1),
884 f64::from_bits(c[9].1),
885 f64::from_bits(c[10].1),
886 f64::from_bits(c[11].1),
887 f64::from_bits(c[12].1),
888 );
889
890 let c = c0;
891
892 let mut p_e = DoubleDouble::mul_f64_add(r, p0, DoubleDouble::from_bit_pair(c[14]));
893 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[13]));
894 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[12]));
895 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[11]));
896 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[10]));
897 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[9]));
898 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[8]));
899 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[7]));
900 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[6]));
901 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[5]));
902 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[4]));
903 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[3]));
904 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[2]));
905 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[1]));
906 p_e = DoubleDouble::mul_add(p_e, r, DoubleDouble::from_bit_pair(c[0]));
907
908 let p = DoubleDouble::from_exact_add(p_e.hi, p_e.lo);
909 let err = f_fmla(
910 p.hi,
911 f64::from_bits(0x3c30000000000000), f64::from_bits(0x3bf0000000000000), );
914 let ub = p.hi + (p.lo + err);
915 let lb = p.hi + (p.lo - err);
916 if ub == lb {
917 return p.to_f64();
918 }
919 y1_small_argument_hard(r, c)
920}
921
922#[cold]
923#[inline(never)]
924fn y1_small_argument_hard(r: DoubleDouble, c: &[(u64, u64); 28]) -> f64 {
925 let mut p = DoubleDouble::from_bit_pair(c[27]);
928 for i in (0..27).rev() {
929 p = DoubleDouble::mul_add(r, p, DoubleDouble::from_bit_pair(c[i]));
930 p = DoubleDouble::from_exact_add(p.hi, p.lo);
931 }
932 p.to_f64()
933}
934
935#[inline]
943pub(crate) fn y1_asympt_fast(x: f64) -> f64 {
944 const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new(
945 f64::from_bits(0xbc8cbc0d30ebfd15),
946 f64::from_bits(0x3fe9884533d43651),
947 );
948 const MPI_OVER_4: DoubleDouble = DoubleDouble::new(
949 f64::from_bits(0xbc81a62633145c07),
950 f64::from_bits(0xbfe921fb54442d18),
951 );
952
953 let recip = if x.to_bits() > 0x7fd000000000000u64 {
954 DoubleDouble::quick_mult_f64(DoubleDouble::from_exact_safe_div(4.0, x), 0.25)
955 } else {
956 DoubleDouble::from_recip(x)
957 };
958
959 let alpha = bessel_1_asympt_alpha_fast(recip);
960 let beta = bessel_1_asympt_beta_fast(recip);
961
962 let AngleReduced { angle } = rem2pi_any(x);
963
964 let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha);
966 let r0 = DoubleDouble::full_dd_add(angle, x0pi34);
967
968 let m_cos = -cos_dd_small_fast(r0);
969 let z0 = DoubleDouble::quick_mult(beta, m_cos);
970 let r_sqrt = DoubleDouble::from_rsqrt_fast(x);
971 let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt);
972 let r = DoubleDouble::quick_mult(scale, z0);
973 let p = DoubleDouble::from_exact_add(r.hi, r.lo);
974 let err = f_fmla(
975 p.hi,
976 f64::from_bits(0x3c40000000000000), f64::from_bits(0x3bf0000000000000), );
979 let ub = p.hi + (p.lo + err);
980 let lb = p.hi + (p.lo - err);
981 if ub == lb {
982 return p.to_f64();
983 }
984 y1_asympt(x, recip, r_sqrt, angle)
985}
986
987fn y1_asympt(x: f64, recip: DoubleDouble, r_sqrt: DoubleDouble, angle: DoubleDouble) -> f64 {
995 const SQRT_2_OVER_PI: DoubleDouble = DoubleDouble::new(
996 f64::from_bits(0xbc8cbc0d30ebfd15),
997 f64::from_bits(0x3fe9884533d43651),
998 );
999 const MPI_OVER_4: DoubleDouble = DoubleDouble::new(
1000 f64::from_bits(0xbc81a62633145c07),
1001 f64::from_bits(0xbfe921fb54442d18),
1002 );
1003
1004 let alpha = bessel_1_asympt_alpha(recip);
1005 let beta = bessel_1_asympt_beta(recip);
1006
1007 let x0pi34 = DoubleDouble::full_dd_sub(MPI_OVER_4, alpha);
1009 let r0 = DoubleDouble::full_dd_add(angle, x0pi34);
1010
1011 let m_cos = -cos_dd_small(r0);
1012 let z0 = DoubleDouble::quick_mult(beta, m_cos);
1013 let scale = DoubleDouble::quick_mult(SQRT_2_OVER_PI, r_sqrt);
1014 let r = DoubleDouble::quick_mult(scale, z0);
1015 let p = DoubleDouble::from_exact_add(r.hi, r.lo);
1016 let err = f_fmla(
1017 p.hi,
1018 f64::from_bits(0x3c30000000000000), f64::from_bits(0x3a80000000000000), );
1021 let ub = p.hi + (p.lo + err);
1022 let lb = p.hi + (p.lo - err);
1023 if ub == lb {
1024 return p.to_f64();
1025 }
1026 y1_asympt_hard(x)
1027}
1028
1029#[cold]
1037#[inline(never)]
1038fn y1_asympt_hard(x: f64) -> f64 {
1039 const SQRT_2_OVER_PI: DyadicFloat128 = DyadicFloat128 {
1040 sign: DyadicSign::Pos,
1041 exponent: -128,
1042 mantissa: 0xcc42299e_a1b28468_7e59e280_5d5c7180_u128,
1043 };
1044
1045 const MPI_OVER_4: DyadicFloat128 = DyadicFloat128 {
1046 sign: DyadicSign::Neg,
1047 exponent: -128,
1048 mantissa: 0xc90fdaa2_2168c234_c4c6628b_80dc1cd1_u128,
1049 };
1050
1051 let x_dyadic = DyadicFloat128::new_from_f64(x);
1052 let recip = DyadicFloat128::accurate_reciprocal(x);
1053
1054 let alpha = bessel_1_asympt_alpha_hard(recip);
1055 let beta = bessel_1_asympt_beta_hard(recip);
1056
1057 let angle = rem2pi_f128(x_dyadic);
1058
1059 let x0pi34 = MPI_OVER_4 - alpha;
1060 let r0 = angle + x0pi34;
1061
1062 let m_cos = cos_f128_small(r0).negated();
1063
1064 let z0 = beta * m_cos;
1065 let r_sqrt = bessel_rsqrt_hard(x, recip);
1066 let scale = SQRT_2_OVER_PI * r_sqrt;
1067 let p = scale * z0;
1068 p.fast_as_f64()
1069}
1070
1071#[cfg(test)]
1072mod tests {
1073 use super::*;
1074
1075 #[test]
1076 fn test_y1() {
1077 assert_eq!(f_y1(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007291282546733975),
1079 -873124540555277200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.);
1080 assert_eq!(f_y1(2.1957931471395398), -0.0007023285780874727);
1081 assert_eq!(
1082 f_y1(f64::from_bits(0x571a31ffe2ff7e9fu64)),
1083 f64::from_bits(0x32e58532f95056ffu64)
1084 );
1085 assert_eq!(
1086 f_y1(f64::from_bits(0x400193bed4dff243)),
1087 0.00000000000000002513306678922122
1088 );
1089 assert_eq!(
1090 f_y1(f64::from_bits(0x3ffc513c569fe78e)),
1091 -0.24189760895998239
1092 );
1093 assert_eq!(
1094 f_y1(f64::from_bits(0x4192391e4c8faa60)),
1095 -0.000000000000000002572292246748134
1096 );
1097 assert_eq!(
1098 f_y1(f64::from_bits(0x403e9e480605283c)),
1099 -0.00000000000000001524456280251315
1100 );
1101 assert_eq!(
1102 f_y1(f64::from_bits(0x40277f9138d43206)),
1103 0.000000000000000006849807120770496
1104 );
1105 assert_eq!(f_y1(f64::INFINITY), 0.);
1106 assert!(f_y1(f64::NEG_INFINITY).is_nan());
1107 assert!(f_y1(f64::NAN).is_nan());
1108 }
1109
1110 #[test]
1111 fn test_y1_edge_cases() {
1112 assert_eq!(f_y1(2.1904620854463985), -0.0034837351616785234);
1113 assert_eq!(f_y1(2.197142201034536), 4.5568985277260593e-7);
1114 assert_eq!(f_y1(1.4000000000000004), -0.4791469742327998);
1115 assert_eq!(f_y1(2.0002288794493848), -0.1069033735586767);
1116 }
1117}