use std::f64::consts::FRAC_2_PI;
use super::bessel_util::{high_word, split_words, FRAC_2_SQRT_PI, HUGE};
const R00: f64 = -6.25e-2; const R01: f64 = 1.407_056_669_551_897e-3; const R02: f64 = -1.599_556_310_840_356e-5; const R03: f64 = 4.967_279_996_095_844_5e-8; const S01: f64 = 1.915_375_995_383_634_6e-2; const S02: f64 = 1.859_467_855_886_309_2e-4; const S03: f64 = 1.177_184_640_426_236_8e-6; const S04: f64 = 5.046_362_570_762_170_4e-9; const S05: f64 = 1.235_422_744_261_379_1e-11;
pub(crate) fn j1(x: f64) -> f64 {
let hx = high_word(x);
let ix = hx & 0x7fffffff;
if ix >= 0x7ff00000 {
return 1.0 / x;
}
let y = x.abs();
if ix >= 0x40000000 {
let s = y.sin();
let c = y.cos();
let mut ss = -s - c;
let mut cc = s - c;
if ix < 0x7fe00000 {
let z = (y + y).cos();
if s * c > 0.0 {
cc = z / ss;
} else {
ss = z / cc;
}
}
let z = if ix > 0x48000000 {
FRAC_2_SQRT_PI * cc / y.sqrt()
} else {
let u = pone(y);
let v = qone(y);
FRAC_2_SQRT_PI * (u * cc - v * ss) / y.sqrt()
};
if hx < 0 {
return -z;
} else {
return z;
}
}
if ix < 0x3e400000 {
if HUGE + x > 1.0 {
return 0.5 * x;
}
}
let z = x * x;
let mut r = z * (R00 + z * (R01 + z * (R02 + z * R03)));
let s = 1.0 + z * (S01 + z * (S02 + z * (S03 + z * (S04 + z * S05))));
r *= x;
x * 0.5 + r / s
}
const U0: [f64; 5] = [
-1.960_570_906_462_389_4e-1,
5.044_387_166_398_113e-2,
-1.912_568_958_757_635_5e-3,
2.352_526_005_616_105e-5,
-9.190_991_580_398_789e-8,
];
const V0: [f64; 5] = [
1.991_673_182_366_499e-2,
2.025_525_810_251_351_7e-4,
1.356_088_010_975_162_3e-6,
6.227_414_523_646_215e-9,
1.665_592_462_079_920_8e-11,
];
pub(crate) fn y1(x: f64) -> f64 {
let (lx, hx) = split_words(x);
let ix = 0x7fffffff & hx;
if ix >= 0x7ff00000 {
return 1.0 / (x + x * x);
}
if (ix | lx) == 0 {
return f64::NEG_INFINITY;
}
if hx < 0 {
return f64::NAN;
}
if ix >= 0x40000000 {
let s = x.sin();
let c = x.cos();
let mut ss = -s - c;
let mut cc = s - c;
if ix < 0x7fe00000 {
let z = (x + x).cos();
if s * c > 0.0 {
cc = z / ss;
} else {
ss = z / cc;
}
}
return if ix > 0x48000000 {
FRAC_2_SQRT_PI * ss / x.sqrt()
} else {
let u = pone(x);
let v = qone(x);
FRAC_2_SQRT_PI * (u * ss + v * cc) / x.sqrt()
};
}
if ix <= 0x3c900000 {
return -FRAC_2_PI / x;
}
let z = x * x;
let u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * U0[4])));
let v = 1.0 + z * (V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * V0[4]))));
x * (u / v) + FRAC_2_PI * (j1(x) * x.ln() - 1.0 / x)
}
const PR8: [f64; 6] = [
0.00000000000000000000e+00,
1.171_874_999_999_886_5e-1,
1.323_948_065_930_735_8e1,
4.120_518_543_073_785_6e2,
3.874_745_389_139_605_3e3,
7.914_479_540_318_917e3,
];
const PS8: [f64; 5] = [
1.142_073_703_756_784_1e2,
3.650_930_834_208_534_6e3,
3.695_620_602_690_334_6e4,
9.760_279_359_349_508e4,
3.080_427_206_278_888e4,
];
const PR5: [f64; 6] = [
1.319_905_195_562_435_2e-11,
1.171_874_931_906_141e-1,
6.802_751_278_684_329,
1.083_081_829_901_891_1e2,
5.176_361_395_331_998e2,
5.287_152_013_633_375e2,
];
const PS5: [f64; 5] = [
5.928_059_872_211_313e1,
9.914_014_187_336_144e2,
5.353_266_952_914_88e3,
7.844_690_317_495_512e3,
1.504_046_888_103_610_6e3,
];
const PR3: [f64; 6] = [
3.025_039_161_373_736e-9,
1.171_868_655_672_535_9e-1,
3.932_977_500_333_156_4,
3.511_940_355_916_369e1,
9.105_501_107_507_813e1,
4.855_906_851_973_649e1,
];
const PS3: [f64; 5] = [
3.479_130_950_012_515e1,
3.367_624_587_478_257_5e2,
1.046_871_399_757_751_3e3,
8.908_113_463_982_564e2,
1.037_879_324_396_392_8e2,
];
const PR2: [f64; 6] = [
1.077_108_301_068_737_4e-7,
1.171_762_194_626_833_5e-1,
2.368_514_966_676_088,
1.224_261_091_482_612_3e1,
1.769_397_112_716_877_3e1,
5.073_523_125_888_185,
];
const PS2: [f64; 5] = [
2.143_648_593_638_214e1,
1.252_902_271_684_027_5e2,
2.322_764_690_571_628e2,
1.176_793_732_871_471e2,
8.364_638_933_716_183,
];
fn pone(x: f64) -> f64 {
let ix = high_word(x) & 0x7fffffff;
let (p, q) = if ix >= 0x40200000 {
(PR8, PS8)
} else if ix >= 0x40122E8B {
(PR5, PS5)
} else if ix >= 0x4006DB6D {
(PR3, PS3)
} else {
(PR2, PS2)
};
let z = 1.0 / (x * x);
let r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
let s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4]))));
1.0 + r / s
}
const QR8: [f64; 6] = [
0.00000000000000000000e+00,
-1.025_390_624_999_927_1e-1,
-1.627_175_345_445_9e1,
-7.596_017_225_139_501e2,
-1.184_980_667_024_295_9e4,
-4.843_851_242_857_503_5e4,
];
const QS8: [f64; 6] = [
1.613_953_697_007_229e2,
7.825_385_999_233_485e3,
1.338_753_362_872_495_8e5,
7.196_577_236_832_409e5,
6.666_012_326_177_764e5,
-2.944_902_643_038_346_4e5,
];
const QR5: [f64; 6] = [
-2.089_799_311_417_641e-11,
-1.025_390_502_413_754_3e-1,
-8.056_448_281_239_36,
-1.836_696_074_748_883_8e2,
-1.373_193_760_655_081_6e3,
-2.612_444_404_532_156_6e3,
];
const QS5: [f64; 6] = [
8.127_655_013_843_358e1,
1.991_798_734_604_859_6e3,
1.746_848_519_249_089e4,
4.985_142_709_103_523e4,
2.794_807_516_389_181_2e4,
-4.719_183_547_951_285e3,
];
const QR3: [f64; 6] = [
-5.078_312_264_617_666e-9,
-1.025_378_298_208_370_9e-1,
-4.610_115_811_394_734,
-5.784_722_165_627_836_4e1,
-2.282_445_407_376_317e2,
-2.192_101_284_789_093_3e2,
];
const QS3: [f64; 6] = [
4.766_515_503_237_295e1,
6.738_651_126_766_997e2,
3.380_152_866_795_263_4e3,
5.547_729_097_207_228e3,
1.903_119_193_388_108e3,
-1.352_011_914_443_073_4e2,
];
const QR2: [f64; 6] = [
-1.783_817_275_109_588_7e-7,
-1.025_170_426_079_855_5e-1,
-2.752_205_682_781_874_6,
-1.966_361_626_437_037_2e1,
-4.232_531_333_728_305e1,
-2.137_192_117_037_040_6e1,
];
const QS2: [f64; 6] = [
2.953_336_290_605_238_5e1,
2.529_815_499_821_905_3e2,
7.575_028_348_686_454e2,
7.393_932_053_204_672e2,
1.559_490_033_366_661_2e2,
-4.959_498_988_226_282,
];
fn qone(x: f64) -> f64 {
let ix = high_word(x) & 0x7fffffff;
let (p, q) = if ix >= 0x40200000 {
(QR8, QS8)
} else if ix >= 0x40122E8B {
(QR5, QS5)
} else if ix >= 0x4006DB6D {
(QR3, QS3)
} else {
(QR2, QS2)
};
let z = 1.0 / (x * x);
let r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
let s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5])))));
(0.375 + r / s) / x
}