| ... | @@ -450,8 +450,7 @@ pub fn __logx(a: f80) callconv(.c) f80 { | ... | @@ -450,8 +450,7 @@ pub fn __logx(a: f80) callconv(.c) f80 { |
| 450 | /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): | 450 | /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): |
| 451 | /// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp | 451 | /// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp |
| 452 | pub fn logq(x: f128) callconv(.c) f128 { | 452 | pub fn logq(x: f128) callconv(.c) f128 { |
| 453 | const bitsize = 7; | 453 | const impl = @import("log_f128.zig"); |
| 454 | const size = 1 << bitsize; | | |
| 455 | | 454 | |
| 456 | if (!math.isFinite(x)) { | 455 | if (!math.isFinite(x)) { |
| 457 | if (math.isNan(x)) { | 456 | if (math.isNan(x)) { |
| ... | @@ -469,74 +468,42 @@ pub fn logq(x: f128) callconv(.c) f128 { | ... | @@ -469,74 +468,42 @@ pub fn logq(x: f128) callconv(.c) f128 { |
| 469 | return math.nan(f128); | 468 | return math.nan(f128); |
| 470 | } | 469 | } |
| 471 | | 470 | |
| 472 | // exp(-1 / 16) rounded down | 471 | if (impl.Proc2.lo < x and x < impl.Proc2.hi) { |
| 473 | const proc2_lo: f128 = 0.939413062813475786119710824622305; | | |
| 474 | // exp(1 / 16) rounded up | | |
| 475 | const proc2_hi: f128 = 1.0644944589178594295633905946428897; | | |
| 476 | if (proc2_lo < x and x < proc2_hi) { | | |
| 477 | const f = x - 1.0; | | |
| 478 | | | |
| 479 | const g = 1 / (2 + f); | | |
| 480 | const u = 2 * f * g; | | |
| 481 | const v = u * u; | | |
| 482 | const uv = u * v; | | |
| 483 | const v64: f64 = @floatCast(v); | | |
| 484 | | | |
| 485 | // Polynomial approximation of log((1 + u / 2) / (1 - u / 2)) | 472 | // Polynomial approximation of log((1 + u / 2) / (1 - u / 2)) |
| 486 | // in [2 * a / (2 + a), 2 * b / (2 + b)] | 473 | // in [2 * a / (2 + a), 2 * b / (2 + b)] |
| 487 | // where a = exp(-1 / 16) - 1 and b = exp(1 / 16) - 1 | 474 | // where a = exp(-1 / 16) - 1 and b = exp(1 / 16) - 1 |
| 488 | const p19 = 2.0165671588771827537210411918018159e-7; | 475 | const poly: impl.Proc2.Poly = .{ |
| 489 | const p17 = 8.97568550755477160981619052649713e-7 + v64 * p19; | 476 | .b1_hi = 1.0, |
| 490 | const p15 = 4.069010449774280288178309893970754e-6 + v64 * p17; | 477 | .b1_lo = 0.0, |
| 491 | const p13 = 1.8780048076832339308077858301484127e-5 + v * p15; | 478 | .b3 = 8.333333333333333333333333333333581e-2, |
| 492 | const p11 = 8.87784090909092440759545734146088e-5 + v * p13; | 479 | .b5 = 1.249999999999999999999999997455655e-2, |
| 493 | const p9 = 4.340277777777777776216500817402857e-4 + v * p11; | 480 | .b7 = 2.2321428571428571428572328745789477e-3, |
| 494 | const p7 = 2.2321428571428571428572328745789477e-3 + v * p9; | 481 | .b9 = 4.340277777777777776216500817402857e-4, |
| 495 | const p5 = 1.249999999999999999999999997455655e-2 + v * p7; | 482 | .b11 = 8.87784090909092440759545734146088e-5, |
| 496 | const p3 = 8.333333333333333333333333333333581e-2; | 483 | .b13 = 1.8780048076832339308077858301484127e-5, |
| 497 | | 484 | .b15 = 4.069010449774280288178309893970754e-6, |
| 498 | const q_hi = uv * p3; | 485 | .b17 = 8.97568550755477160981619052649713e-7, |
| 499 | const q_lo = uv * v * p5; | 486 | .b19 = 2.0165671588771827537210411918018159e-7, |
| 500 | const q = q_hi + q_lo; | 487 | }; |
| 501 | | 488 | return impl.proc2(.{ .poly = poly }, x); |
| 502 | const fa: f128 = @as(f64, @floatCast(f)); | | |
| 503 | const ua: f128 = @as(f64, @floatCast(u)); | | |
| 504 | | | |
| 505 | const fb: f128 = f - fa; | | |
| 506 | const ub: f128 = ((2 * (f - ua) - ua * fa) - ua * fb) * g; | | |
| 507 | | | |
| 508 | return ua + (ub + q); | | |
| 509 | } | 489 | } |
| 510 | | 490 | |
| 511 | const ym = frexp2(x); | | |
| 512 | const y = ym.significand; | | |
| 513 | const m = ym.exponent; | | |
| 514 | | | |
| 515 | const F0 = @round(math.ldexp(y, bitsize)); | | |
| 516 | const j0: usize = @intFromFloat(F0); | | |
| 517 | const j = j0 - size; | | |
| 518 | const F = math.ldexp(F0, -bitsize); | | |
| 519 | const f = y - F; | | |
| 520 | | | |
| 521 | const u = (f + f) / (y + F); | | |
| 522 | const v = u * u; | | |
| 523 | const v64: f64 = @floatCast(v); | | |
| 524 | | | |
| 525 | // Polynomial approximation of log(1 + 2 * u / (2 - u)) | 491 | // Polynomial approximation of log(1 + 2 * u / (2 - u)) |
| 526 | // in [-(2 * fmax) / (2 + fmax), (2 * fmax) / (2 - fmax)] | 492 | // in [-(2 * fmax) / (2 + fmax), (2 * fmax) / (2 - fmax)] |
| 527 | // where fmax = 0.5 / size | 493 | // where fmax = 0.5 / size |
| 528 | const p11 = 8.877925718782769769445565656611838e-5; | 494 | const poly: impl.Proc1.Poly = .{ |
| 529 | const p9 = 4.340277777635300605611118803507141e-4 + v64 * p11; | 495 | .a1 = 1.0, |
| 530 | const p7 = 2.2321428571428572515097318595359542e-3 + v * p9; | 496 | .a3 = 8.333333333333333333333333333372414e-2, |
| 531 | const p5 = 1.249999999999999999999963839743372e-2 + v * p7; | 497 | .a5 = 1.249999999999999999999963839743372e-2, |
| 532 | const p3 = 8.333333333333333333333333333372414e-2 + v * p5; | 498 | .a7 = 2.2321428571428572515097318595359542e-3, |
| 533 | | 499 | .a9 = 4.340277777635300605611118803507141e-4, |
| 534 | const q = u * v * p3; | 500 | .a11 = 8.877925718782769769445565656611838e-5, |
| | 501 | }; |
| 535 | | 502 | |
| 536 | // log1p_tab[j].hi = 2^-n * round-to-integer(2^n * l) | 503 | // tab[j].hi = 2^-n * round-to-integer(2^n * l) |
| 537 | // log1p_tab[j].lo = round-to-nearest-f128(l - log1p_tab[j].hi) | 504 | // tab[j].lo = round-to-nearest-f128(l - tab[j].hi) |
| 538 | // where n = 97 and l = log(1 + j / size) | 505 | // where n = 97 and l = log(1 + j / size) |
| 539 | const log1p_tab = [size + 1]struct { hi: f128, lo: f128 }{ | 506 | const tab = [impl.size + 1]impl.Proc1.HiLo{ |
| 540 | .{ .hi = 0, .lo = 0 }, | 507 | .{ .hi = 0, .lo = 0 }, |
| 541 | .{ .hi = 0x1.fe02a6b106788fc3769039p-8, .lo = 0x1.dc282d2b3db2c3ef9a073a876702p-100 }, | 508 | .{ .hi = 0x1.fe02a6b106788fc3769039p-8, .lo = 0x1.dc282d2b3db2c3ef9a073a876702p-100 }, |
| 542 | .{ .hi = 0x1.fc0a8b0fc03e3cf9eda74d4p-7, .lo = -0x1.0a8552414fc416fc223acca2ebfp-100 }, | 509 | .{ .hi = 0x1.fc0a8b0fc03e3cf9eda74d4p-7, .lo = -0x1.0a8552414fc416fc223acca2ebfp-100 }, |
| ... | @@ -667,11 +634,8 @@ pub fn logq(x: f128) callconv(.c) f128 { | ... | @@ -667,11 +634,8 @@ pub fn logq(x: f128) callconv(.c) f128 { |
| 667 | .{ .hi = 0x1.60e32f44788d8ca7c895a0b5p-1, .lo = -0x1.3557995d063914a66aa81ead3fdbp-101 }, | 634 | .{ .hi = 0x1.60e32f44788d8ca7c895a0b5p-1, .lo = -0x1.3557995d063914a66aa81ead3fdbp-101 }, |
| 668 | .{ .hi = 0x1.62e42fefa39ef35793c7673p-1, .lo = 0x1.f97b57a079a193394c5b16c5068cp-103 }, | 635 | .{ .hi = 0x1.62e42fefa39ef35793c7673p-1, .lo = 0x1.f97b57a079a193394c5b16c5068cp-103 }, |
| 669 | }; | 636 | }; |
| 670 | const xm: f128 = @floatFromInt(m); | | |
| 671 | const l_hi = xm * log1p_tab[128].hi + log1p_tab[j].hi; | | |
| 672 | const l_lo = xm * log1p_tab[128].lo + log1p_tab[j].lo; | | |
| 673 | | 637 | |
| 674 | return l_hi + (u + (q + l_lo)); | 638 | return impl.proc1(.{ .poly = poly, .tab = tab }, x); |
| 675 | } | 639 | } |
| 676 | | 640 | |
| 677 | pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { | 641 | pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { |