| author | |
| committer | |
| log | 51509fe63bd94c2067bdc31962775ed3742b657f |
| tree | 72accfbf3909751acbeadf581273387279a97b08 |
| parent | ef13a373bcce33fd74dcdf3aaa86f21a601d35ec |
2 files changed, 380 insertions(+), 16 deletions(-)
lib/std/math/acos.zig+192-8| ... | ... | @@ -4,6 +4,12 @@ |
| 4 | 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/acosf.c |
| 5 | 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/acos.c |
| 6 | 6 | // https://git.musl-libc.org/cgit/musl/tree/src/math/acosl.c |
| 7 | // | |
| 8 | // Ported from ARM-software, which is licensed under the MIT license: | |
| 9 | // https://github.com/ARM-software/optimized-routines/blob/master/LICENSE | |
| 10 | // | |
| 11 | // https://github.com/ARM-software/optimized-routines/blob/master/math/aarch64/advsimd/acosf.c | |
| 12 | // https://github.com/ARM-software/optimized-routines/blob/master/math/aarch64/advsimd/acos.c | |
| 7 | 13 | |
| 8 | 14 | const std = @import("../std.zig"); |
| 9 | 15 | const math = std.math; |
| ... | ... | @@ -17,14 +23,22 @@ const native_endian = builtin.cpu.arch.endian(); |
| 17 | 23 | /// - acos(x) = nan if x < -1 or x > 1 |
| 18 | 24 | pub fn acos(x: anytype) @TypeOf(x) { |
| 19 | 25 | const T = @TypeOf(x); |
| 20 | return switch (T) { | |
| 21 | f16 => acosBinary16(x), | |
| 22 | f32 => acosBinary32(x), | |
| 23 | f64 => acosBinary64(x), | |
| 24 | f80 => acosExtended80(x), | |
| 25 | f128 => acosBinary128(x), | |
| 26 | else => @compileError("acos not implemented for " ++ @typeName(T)), | |
| 27 | }; | |
| 26 | switch (@typeInfo(T)) { | |
| 27 | .float => |info| switch (info.bits) { | |
| 28 | 16 => return acosBinary16(x), | |
| 29 | 32 => return acosBinary32(x), | |
| 30 | 64 => return acosBinary64(x), | |
| 31 | 80 => return acosExtended80(x), | |
| 32 | 128 => return acosBinary128(x), | |
| 33 | else => comptime unreachable, | |
| 34 | }, | |
| 35 | .vector => |info| switch (info.child) { | |
| 36 | f32 => return acosBinary32Vec(info.len, x), | |
| 37 | f64 => return acosBinary64Vec(info.len, x), | |
| 38 | else => @compileError("unimplemented"), | |
| 39 | }, | |
| 40 | else => comptime unreachable, | |
| 41 | } | |
| 28 | 42 | } |
| 29 | 43 | |
| 30 | 44 | fn approxBinary16(z: f32) f32 { |
| ... | ... | @@ -441,3 +455,173 @@ test "acosBinary128" { |
| 441 | 455 | try testing.expectApproxEqAbs(0x1.513270e671db2d840f20b0186c2cp1, acosBinary128(-0x1.bf887b8c4e33cbef59993056f3dep-1), math.floatEpsAt(f128, 0x1.513270e671db2d840f20b0186c2cp1)); |
| 442 | 456 | try testing.expectApproxEqAbs(0x1.70851a509f0e8bfbe780aa8f29f9p0, acosBinary128(0x1.0c0f600ab6f9c84c6102942044cep-3), math.floatEpsAt(f128, 0x1.70851a509f0e8bfbe780aa8f29f9p0)); |
| 443 | 457 | } |
| 458 | ||
| 459 | fn acosBinary32Vec(comptime vec_len: comptime_int, x: @Vector(vec_len, f32)) @TypeOf(x) { | |
| 460 | const pi: @Vector(vec_len, f32) = @splat(math.pi); | |
| 461 | const pi_over_2: @Vector(vec_len, f32) = @splat(math.pi / 2.0); | |
| 462 | const zero: @Vector(vec_len, f32) = @splat(0.0); | |
| 463 | const half: @Vector(vec_len, f32) = @splat(0.5); | |
| 464 | const neg_one: @Vector(vec_len, f32) = @splat(-1.0); | |
| 465 | const two: @Vector(vec_len, f32) = @splat(2.0); | |
| 466 | const c0: @Vector(vec_len, f32) = @splat(0x1.55555ep-3); | |
| 467 | const c1: @Vector(vec_len, f32) = @splat(0x1.33261ap-4); | |
| 468 | const c2: @Vector(vec_len, f32) = @splat(0x1.70d7dcp-5); | |
| 469 | const c3: @Vector(vec_len, f32) = @splat(0x1.b059dp-6); | |
| 470 | const c4: @Vector(vec_len, f32) = @splat(0x1.3af7d8p-5); | |
| 471 | ||
| 472 | const ax = @abs(x); | |
| 473 | const ax_lt_half = ax < half; | |
| 474 | const is_neg = x < zero; | |
| 475 | const z2 = @select(f32, ax_lt_half, x * x, @mulAdd(@Vector(vec_len, f32), -half, ax, half)); | |
| 476 | const z = @select(f32, ax_lt_half, ax, @sqrt(z2)); | |
| 477 | const z3 = z2 * z; | |
| 478 | const p3_4 = @mulAdd(@Vector(vec_len, f32), z2, c4, c3); | |
| 479 | const p2_4 = @mulAdd(@Vector(vec_len, f32), z2, p3_4, c2); | |
| 480 | const p1_4 = @mulAdd(@Vector(vec_len, f32), z2, p2_4, c1); | |
| 481 | const p0_4 = @mulAdd(@Vector(vec_len, f32), z2, p1_4, c0); | |
| 482 | const p = @mulAdd(@Vector(vec_len, f32), z3, p0_4, z); | |
| 483 | const mul = @select(f32, ax_lt_half, neg_one, two); | |
| 484 | const add = @select(f32, ax_lt_half, pi_over_2, @select(f32, is_neg, pi, zero)); | |
| 485 | return @mulAdd(@Vector(vec_len, f32), mul, @select(f32, is_neg, -p, p), add); | |
| 486 | } | |
| 487 | ||
| 488 | fn acosBinary64Vec(comptime vec_len: comptime_int, x: @Vector(vec_len, f64)) @TypeOf(x) { | |
| 489 | const pi: @Vector(vec_len, f64) = @splat(math.pi); | |
| 490 | const pi_over_2: @Vector(vec_len, f64) = @splat(math.pi / 2.0); | |
| 491 | const zero: @Vector(vec_len, f64) = @splat(0.0); | |
| 492 | const half: @Vector(vec_len, f64) = @splat(0.5); | |
| 493 | const neg_one: @Vector(vec_len, f64) = @splat(-1.0); | |
| 494 | const two: @Vector(vec_len, f64) = @splat(2.0); | |
| 495 | const c0: @Vector(vec_len, f64) = @splat(0x1.555555555554ep-3); | |
| 496 | const c1: @Vector(vec_len, f64) = @splat(0x1.3333333337233p-4); | |
| 497 | const c2: @Vector(vec_len, f64) = @splat(0x1.6db6db67f6d9fp-5); | |
| 498 | const c3: @Vector(vec_len, f64) = @splat(0x1.f1c71fbd29fbbp-6); | |
| 499 | const c4: @Vector(vec_len, f64) = @splat(0x1.6e8b264d467d6p-6); | |
| 500 | const c5: @Vector(vec_len, f64) = @splat(0x1.1c5997c357e9dp-6); | |
| 501 | const c6: @Vector(vec_len, f64) = @splat(0x1.c86a22cd9389dp-7); | |
| 502 | const c7: @Vector(vec_len, f64) = @splat(0x1.856073c22ebbep-7); | |
| 503 | const c8: @Vector(vec_len, f64) = @splat(0x1.fd1151acb6bedp-8); | |
| 504 | const c9: @Vector(vec_len, f64) = @splat(0x1.087182f799c1dp-6); | |
| 505 | const c10: @Vector(vec_len, f64) = @splat(-0x1.6602748120927p-7); | |
| 506 | const c11: @Vector(vec_len, f64) = @splat(0x1.cfa0dd1f9478p-6); | |
| 507 | ||
| 508 | const ax = @abs(x); | |
| 509 | const ax_lt_half = ax < half; | |
| 510 | const is_neg = x < zero; | |
| 511 | const z2 = @select(f64, ax_lt_half, x * x, @mulAdd(@Vector(vec_len, f64), -half, ax, half)); | |
| 512 | const z = @select(f64, ax_lt_half, ax, @sqrt(z2)); | |
| 513 | const z3 = z2 * z; | |
| 514 | const z4 = z2 * z2; | |
| 515 | const z8 = z4 * z4; | |
| 516 | const p0_1 = @mulAdd(@Vector(vec_len, f64), z2, c1, c0); | |
| 517 | const p2_3 = @mulAdd(@Vector(vec_len, f64), z2, c3, c2); | |
| 518 | const p0_3 = @mulAdd(@Vector(vec_len, f64), z4, p2_3, p0_1); | |
| 519 | const p4_5 = @mulAdd(@Vector(vec_len, f64), z2, c5, c4); | |
| 520 | const p6_7 = @mulAdd(@Vector(vec_len, f64), z2, c7, c6); | |
| 521 | const p4_7 = @mulAdd(@Vector(vec_len, f64), z4, p6_7, p4_5); | |
| 522 | const p8_9 = @mulAdd(@Vector(vec_len, f64), z2, c9, c8); | |
| 523 | const p10_11 = @mulAdd(@Vector(vec_len, f64), z2, c11, c10); | |
| 524 | const p8_11 = @mulAdd(@Vector(vec_len, f64), z4, p10_11, p8_9); | |
| 525 | const p4_11 = @mulAdd(@Vector(vec_len, f64), z8, p8_11, p4_7); | |
| 526 | const p0_11 = @mulAdd(@Vector(vec_len, f64), z8, p4_11, p0_3); | |
| 527 | const p = @mulAdd(@Vector(vec_len, f64), z3, p0_11, z); | |
| 528 | const mul = @select(f64, ax_lt_half, neg_one, two); | |
| 529 | const add = @select(f64, ax_lt_half, pi_over_2, @select(f64, is_neg, pi, zero)); | |
| 530 | return @mulAdd(@Vector(vec_len, f64), mul, @select(f64, is_neg, -p, p), add); | |
| 531 | } | |
| 532 | ||
| 533 | test "acosBinary32Vec.special" { | |
| 534 | const input: @Vector(8, f32) = .{ | |
| 535 | 0x0p+0, | |
| 536 | -0x1p+0, | |
| 537 | 0x1p+0, | |
| 538 | 0x1.000002p+0, | |
| 539 | -0x1.000002p+0, | |
| 540 | math.inf(f32), | |
| 541 | -math.inf(f32), | |
| 542 | math.nan(f32), | |
| 543 | }; | |
| 544 | const output = acosBinary32Vec(8, input); | |
| 545 | try testing.expectApproxEqAbs(0x1.921fb6p+0, output[0], math.floatEpsAt(f32, 0x1.921fb6p+0)); | |
| 546 | try testing.expectApproxEqAbs(0x1.921fb6p+1, output[1], math.floatEpsAt(f32, 0x1.921fb6p+1)); | |
| 547 | try testing.expectEqual(0x0p+0, output[2]); | |
| 548 | try testing.expect(math.isNan(output[3])); | |
| 549 | try testing.expect(math.isNan(output[4])); | |
| 550 | try testing.expect(math.isNan(output[5])); | |
| 551 | try testing.expect(math.isNan(output[6])); | |
| 552 | try testing.expect(math.isNan(output[7])); | |
| 553 | } | |
| 554 | ||
| 555 | test "acosBinary32Vec" { | |
| 556 | const input: @Vector(10, f32) = .{ | |
| 557 | -0x1.13284cp-2, | |
| 558 | 0x1.6ca8ep-1, | |
| 559 | 0x1.c2ca6p-1, | |
| 560 | -0x1.55f12p-1, | |
| 561 | -0x1.15679ep-2, | |
| 562 | -0x1.41e132p-5, | |
| 563 | 0x1.281b0ep-1, | |
| 564 | 0x1.b5ce34p-1, | |
| 565 | -0x1.583482p-3, | |
| 566 | -0x1.ea8224p-1, | |
| 567 | }; | |
| 568 | const output = acosBinary32Vec(10, input); | |
| 569 | try testing.expectApproxEqAbs(0x1.d7c4e6p+0, output[0], math.floatEpsAt(f32, 0x1.d7c4e6p+0)); | |
| 570 | try testing.expectApproxEqAbs(0x1.8e6756p-1, output[1], math.floatEpsAt(f32, 0x1.8e6756p-1)); | |
| 571 | try testing.expectApproxEqAbs(0x1.f9d74cp-2, output[2], math.floatEpsAt(f32, 0x1.f9d74cp-2)); | |
| 572 | try testing.expectApproxEqAbs(0x1.26abdcp+1, output[3], math.floatEpsAt(f32, 0x1.26abdcp+1)); | |
| 573 | try testing.expectApproxEqAbs(0x1.d85a44p+0, output[4], math.floatEpsAt(f32, 0x1.d85a44p+0)); | |
| 574 | try testing.expectApproxEqAbs(0x1.9c2f68p+0, output[5], math.floatEpsAt(f32, 0x1.9c2f68p+0)); | |
| 575 | try testing.expectApproxEqAbs(0x1.e881bp-1, output[6], math.floatEpsAt(f32, 0x1.e881bp-1)); | |
| 576 | try testing.expectApproxEqAbs(0x1.1713f6p-1, output[7], math.floatEpsAt(f32, 0x1.1713f6p-1)); | |
| 577 | try testing.expectApproxEqAbs(0x1.bd5accp+0, output[8], math.floatEpsAt(f32, 0x1.bd5accp+0)); | |
| 578 | try testing.expectApproxEqAbs(0x1.6ce7d8p+1, output[9], math.floatEpsAt(f32, 0x1.6ce7d8p+1)); | |
| 579 | } | |
| 580 | ||
| 581 | test "acosBinary64Vec.special" { | |
| 582 | const input: @Vector(8, f64) = .{ | |
| 583 | 0x0p+0, | |
| 584 | -0x1p+0, | |
| 585 | 0x1p+0, | |
| 586 | 0x1.0000000000001p+0, | |
| 587 | -0x1.0000000000001p+0, | |
| 588 | math.inf(f64), | |
| 589 | -math.inf(f64), | |
| 590 | math.nan(f64), | |
| 591 | }; | |
| 592 | const output = acosBinary64Vec(8, input); | |
| 593 | try testing.expectApproxEqAbs(0x1.921fb54442d18p+0, output[0], math.floatEpsAt(f64, 0x1.921fb54442d18p+0)); | |
| 594 | try testing.expectApproxEqAbs(0x1.921fb54442d18p+1, output[1], math.floatEpsAt(f64, 0x1.921fb54442d18p+1)); | |
| 595 | try testing.expectEqual(0x0p+0, output[2]); | |
| 596 | try testing.expect(math.isNan(output[3])); | |
| 597 | try testing.expect(math.isNan(output[4])); | |
| 598 | try testing.expect(math.isNan(output[5])); | |
| 599 | try testing.expect(math.isNan(output[6])); | |
| 600 | try testing.expect(math.isNan(output[7])); | |
| 601 | } | |
| 602 | ||
| 603 | test "acosBinary64Vec" { | |
| 604 | const input: @Vector(10, f64) = .{ | |
| 605 | -0x1.13284b2b5006dp-2, | |
| 606 | 0x1.6ca8dfb825911p-1, | |
| 607 | 0x1.c2ca609de7505p-1, | |
| 608 | -0x1.55f11fba96889p-1, | |
| 609 | -0x1.15679e27084ddp-2, | |
| 610 | -0x1.41e131b093c41p-5, | |
| 611 | 0x1.281b0d18455f5p-1, | |
| 612 | 0x1.b5ce34a51b239p-1, | |
| 613 | -0x1.583481079de4dp-3, | |
| 614 | -0x1.ea8223103b871p-1, | |
| 615 | }; | |
| 616 | const output = acosBinary64Vec(10, input); | |
| 617 | try testing.expectApproxEqAbs(0x1.d7c4e61020905p+0, output[0], math.floatEpsAt(f64, 0x1.d7c4e61020905p+0)); | |
| 618 | try testing.expectApproxEqAbs(0x1.8e6756e27c366p-1, output[1], math.floatEpsAt(f64, 0x1.8e6756e27c366p-1)); | |
| 619 | try testing.expectApproxEqAbs(0x1.f9d748eaf956p-2, output[2], math.floatEpsAt(f64, 0x1.f9d748eaf956p-2)); | |
| 620 | try testing.expectApproxEqAbs(0x1.26abdc68d07aap+1, output[3], math.floatEpsAt(f64, 0x1.26abdc68d07aap+1)); | |
| 621 | try testing.expectApproxEqAbs(0x1.d85a44ea44fe4p+0, output[4], math.floatEpsAt(f64, 0x1.d85a44ea44fe4p+0)); | |
| 622 | try testing.expectApproxEqAbs(0x1.9c2f688eee8abp+0, output[5], math.floatEpsAt(f64, 0x1.9c2f688eee8abp+0)); | |
| 623 | try testing.expectApproxEqAbs(0x1.e881b1d4eb2a1p-1, output[6], math.floatEpsAt(f64, 0x1.e881b1d4eb2a1p-1)); | |
| 624 | try testing.expectApproxEqAbs(0x1.1713f567a87efp-1, output[7], math.floatEpsAt(f64, 0x1.1713f567a87efp-1)); | |
| 625 | try testing.expectApproxEqAbs(0x1.bd5acbe8fcc59p+0, output[8], math.floatEpsAt(f64, 0x1.bd5acbe8fcc59p+0)); | |
| 626 | try testing.expectApproxEqAbs(0x1.6ce7d66f628e5p+1, output[9], math.floatEpsAt(f64, 0x1.6ce7d66f628e5p+1)); | |
| 627 | } |
lib/std/math/asin.zig+188-8| ... | ... | @@ -4,6 +4,12 @@ |
| 4 | 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asinf.c |
| 5 | 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asin.c |
| 6 | 6 | // https://git.musl-libc.org/cgit/musl/tree/src/math/asinl.c |
| 7 | // | |
| 8 | // Ported from ARM-software, which is licensed under the MIT license: | |
| 9 | // https://github.com/ARM-software/optimized-routines/blob/master/LICENSE | |
| 10 | // | |
| 11 | // https://github.com/ARM-software/optimized-routines/blob/master/math/aarch64/advsimd/asinf.c | |
| 12 | // https://github.com/ARM-software/optimized-routines/blob/master/math/aarch64/advsimd/asin.c | |
| 7 | 13 | |
| 8 | 14 | const std = @import("../std.zig"); |
| 9 | 15 | const math = std.math; |
| ... | ... | @@ -19,14 +25,22 @@ const native_endian = builtin.cpu.arch.endian(); |
| 19 | 25 | /// - asin(x) = nan if x < -1 or x > 1 |
| 20 | 26 | pub fn asin(x: anytype) @TypeOf(x) { |
| 21 | 27 | const T = @TypeOf(x); |
| 22 | return switch (T) { | |
| 23 | f16 => asinBinary16(x), | |
| 24 | f32 => asinBinary32(x), | |
| 25 | f64 => asinBinary64(x), | |
| 26 | f80 => asinExtended80(x), | |
| 27 | f128 => asinBinary128(x), | |
| 28 | else => @compileError("asin not implemented for " ++ @typeName(T)), | |
| 29 | }; | |
| 28 | switch (@typeInfo(T)) { | |
| 29 | .float => |info| switch (info.bits) { | |
| 30 | 16 => return asinBinary16(x), | |
| 31 | 32 => return asinBinary32(x), | |
| 32 | 64 => return asinBinary64(x), | |
| 33 | 80 => return asinExtended80(x), | |
| 34 | 128 => return asinBinary128(x), | |
| 35 | else => comptime unreachable, | |
| 36 | }, | |
| 37 | .vector => |info| switch (info.child) { | |
| 38 | f32 => return asinBinary32Vec(info.len, x), | |
| 39 | f64 => return asinBinary64Vec(info.len, x), | |
| 40 | else => @compileError("unimplemented"), | |
| 41 | }, | |
| 42 | else => comptime unreachable, | |
| 43 | } | |
| 30 | 44 | } |
| 31 | 45 | |
| 32 | 46 | fn approxBinary16(z: f32) f32 { |
| ... | ... | @@ -435,3 +449,169 @@ test "asinBinary128" { |
| 435 | 449 | try testing.expectApproxEqAbs(-0x1.97f1092fd94ac0fdfddae2e1222bp-1, asinBinary128(-0x1.6e210214e40edf6c8479998189d1p-1), math.floatEpsAt(f128, -0x1.97f1092fd94ac0fdfddae2e1222bp-1)); |
| 436 | 450 | try testing.expectApproxEqAbs(-0x1.97b62bc5ae6512093828828325e1p-3, asinBinary128(-0x1.95061bf93ed6986a45d20f0e1064p-3), math.floatEpsAt(f128, -0x1.97b62bc5ae6512093828828325e1p-3)); |
| 437 | 451 | } |
| 452 | ||
| 453 | fn asinBinary32Vec(comptime vec_len: comptime_int, x: @Vector(vec_len, f32)) @TypeOf(x) { | |
| 454 | const pi_over_2: @Vector(vec_len, f32) = @splat(math.pi / 2.0); | |
| 455 | const zero: @Vector(vec_len, f32) = @splat(0.0); | |
| 456 | const half: @Vector(vec_len, f32) = @splat(0.5); | |
| 457 | const neg_two: @Vector(vec_len, f32) = @splat(-2.0); | |
| 458 | const c0: @Vector(vec_len, f32) = @splat(0x1.55555ep-3); | |
| 459 | const c1: @Vector(vec_len, f32) = @splat(0x1.33261ap-4); | |
| 460 | const c2: @Vector(vec_len, f32) = @splat(0x1.70d7dcp-5); | |
| 461 | const c3: @Vector(vec_len, f32) = @splat(0x1.b059dp-6); | |
| 462 | const c4: @Vector(vec_len, f32) = @splat(0x1.3af7d8p-5); | |
| 463 | ||
| 464 | const ax = @abs(x); | |
| 465 | const ax_lt_half = ax < half; | |
| 466 | const z2 = @select(f32, ax_lt_half, x * x, @mulAdd(@Vector(vec_len, f32), -half, ax, half)); | |
| 467 | const z = @select(f32, ax_lt_half, ax, @sqrt(z2)); | |
| 468 | const z3 = z2 * z; | |
| 469 | const p3_4 = @mulAdd(@Vector(vec_len, f32), z2, c4, c3); | |
| 470 | const p2_4 = @mulAdd(@Vector(vec_len, f32), z2, p3_4, c2); | |
| 471 | const p1_4 = @mulAdd(@Vector(vec_len, f32), z2, p2_4, c1); | |
| 472 | const p0_4 = @mulAdd(@Vector(vec_len, f32), z2, p1_4, c0); | |
| 473 | const p = @mulAdd(@Vector(vec_len, f32), z3, p0_4, z); | |
| 474 | const y = @select(f32, ax_lt_half, p, @mulAdd(@Vector(vec_len, f32), p, neg_two, pi_over_2)); | |
| 475 | return @select(f32, x < zero, -y, y); | |
| 476 | } | |
| 477 | ||
| 478 | fn asinBinary64Vec(comptime vec_len: comptime_int, x: @Vector(vec_len, f64)) @TypeOf(x) { | |
| 479 | const pi_over_2: @Vector(vec_len, f64) = @splat(math.pi / 2.0); | |
| 480 | const zero: @Vector(vec_len, f64) = @splat(0.0); | |
| 481 | const half: @Vector(vec_len, f64) = @splat(0.5); | |
| 482 | const neg_two: @Vector(vec_len, f64) = @splat(-2.0); | |
| 483 | const c0: @Vector(vec_len, f64) = @splat(0x1.555555555554ep-3); | |
| 484 | const c1: @Vector(vec_len, f64) = @splat(0x1.3333333337233p-4); | |
| 485 | const c2: @Vector(vec_len, f64) = @splat(0x1.6db6db67f6d9fp-5); | |
| 486 | const c3: @Vector(vec_len, f64) = @splat(0x1.f1c71fbd29fbbp-6); | |
| 487 | const c4: @Vector(vec_len, f64) = @splat(0x1.6e8b264d467d6p-6); | |
| 488 | const c5: @Vector(vec_len, f64) = @splat(0x1.1c5997c357e9dp-6); | |
| 489 | const c6: @Vector(vec_len, f64) = @splat(0x1.c86a22cd9389dp-7); | |
| 490 | const c7: @Vector(vec_len, f64) = @splat(0x1.856073c22ebbep-7); | |
| 491 | const c8: @Vector(vec_len, f64) = @splat(0x1.fd1151acb6bedp-8); | |
| 492 | const c9: @Vector(vec_len, f64) = @splat(0x1.087182f799c1dp-6); | |
| 493 | const c10: @Vector(vec_len, f64) = @splat(-0x1.6602748120927p-7); | |
| 494 | const c11: @Vector(vec_len, f64) = @splat(0x1.cfa0dd1f9478p-6); | |
| 495 | ||
| 496 | const ax = @abs(x); | |
| 497 | const ax_lt_half = ax < half; | |
| 498 | const z2 = @select(f64, ax_lt_half, x * x, @mulAdd(@Vector(vec_len, f64), -half, ax, half)); | |
| 499 | const z = @select(f64, ax_lt_half, ax, @sqrt(z2)); | |
| 500 | const z3 = z2 * z; | |
| 501 | const z4 = z2 * z2; | |
| 502 | const z8 = z4 * z4; | |
| 503 | const p0_1 = @mulAdd(@Vector(vec_len, f64), z2, c1, c0); | |
| 504 | const p2_3 = @mulAdd(@Vector(vec_len, f64), z2, c3, c2); | |
| 505 | const p0_3 = @mulAdd(@Vector(vec_len, f64), z4, p2_3, p0_1); | |
| 506 | const p4_5 = @mulAdd(@Vector(vec_len, f64), z2, c5, c4); | |
| 507 | const p6_7 = @mulAdd(@Vector(vec_len, f64), z2, c7, c6); | |
| 508 | const p4_7 = @mulAdd(@Vector(vec_len, f64), z4, p6_7, p4_5); | |
| 509 | const p8_9 = @mulAdd(@Vector(vec_len, f64), z2, c9, c8); | |
| 510 | const p10_11 = @mulAdd(@Vector(vec_len, f64), z2, c11, c10); | |
| 511 | const p8_11 = @mulAdd(@Vector(vec_len, f64), z4, p10_11, p8_9); | |
| 512 | const p4_11 = @mulAdd(@Vector(vec_len, f64), z8, p8_11, p4_7); | |
| 513 | const p0_11 = @mulAdd(@Vector(vec_len, f64), z8, p4_11, p0_3); | |
| 514 | const p = @mulAdd(@Vector(vec_len, f64), z3, p0_11, z); | |
| 515 | const y = @select(f64, ax_lt_half, p, @mulAdd(@Vector(vec_len, f64), p, neg_two, pi_over_2)); | |
| 516 | return @select(f64, x < zero, -y, y); | |
| 517 | } | |
| 518 | ||
| 519 | test "asinBinary32Vec.special" { | |
| 520 | const input: @Vector(9, f32) = .{ | |
| 521 | 0x1p+0, | |
| 522 | -0x1p+0, | |
| 523 | 0x0p+0, | |
| 524 | -0x0p+0, | |
| 525 | 0x1.000002p+0, | |
| 526 | -0x1.000002p+0, | |
| 527 | math.inf(f32), | |
| 528 | -math.inf(f32), | |
| 529 | math.nan(f32), | |
| 530 | }; | |
| 531 | const output = asinBinary32Vec(9, input); | |
| 532 | try testing.expectApproxEqAbs(0x1.921fb6p+0, output[0], math.floatEpsAt(f32, 0x1.921fb6p+0)); | |
| 533 | try testing.expectApproxEqAbs(-0x1.921fb6p+0, output[1], math.floatEpsAt(f32, -0x1.921fb6p+0)); | |
| 534 | try testing.expectEqual(0x0p+0, output[2]); | |
| 535 | try testing.expectEqual(0x0p+0, output[3]); | |
| 536 | try testing.expect(math.isNan(output[4])); | |
| 537 | try testing.expect(math.isNan(output[5])); | |
| 538 | try testing.expect(math.isNan(output[6])); | |
| 539 | try testing.expect(math.isNan(output[7])); | |
| 540 | try testing.expect(math.isNan(output[8])); | |
| 541 | } | |
| 542 | ||
| 543 | test "asinBinary32Vec" { | |
| 544 | const input: @Vector(10, f32) = .{ | |
| 545 | -0x1.4c2906p-4, | |
| 546 | 0x1.05fcfap-1, | |
| 547 | 0x1.fab976p-2, | |
| 548 | 0x1.8b4b8cp-1, | |
| 549 | 0x1.7117c2p-1, | |
| 550 | 0x1.e5e112p-5, | |
| 551 | -0x1.07673p-2, | |
| 552 | -0x1.2108dep-2, | |
| 553 | -0x1.4e6e6cp-1, | |
| 554 | 0x1.22a16ap-1, | |
| 555 | }; | |
| 556 | const output = asinBinary32Vec(10, input); | |
| 557 | try testing.expectApproxEqAbs(-0x1.4c868p-4, output[0], math.floatEpsAt(f32, -0x1.4c868p-4)); | |
| 558 | try testing.expectApproxEqAbs(0x1.130648p-1, output[1], math.floatEpsAt(f32, 0x1.130648p-1)); | |
| 559 | try testing.expectApproxEqAbs(0x1.090abcp-1, output[2], math.floatEpsAt(f32, 0x1.090abcp-1)); | |
| 560 | try testing.expectApproxEqAbs(0x1.c39fa2p-1, output[3], math.floatEpsAt(f32, 0x1.c39fa2p-1)); | |
| 561 | try testing.expectApproxEqAbs(0x1.9c332p-1, output[4], math.floatEpsAt(f32, 0x1.9c332p-1)); | |
| 562 | try testing.expectApproxEqAbs(0x1.e62a1cp-5, output[5], math.floatEpsAt(f32, 0x1.e62a1cp-5)); | |
| 563 | try testing.expectApproxEqAbs(-0x1.0a65dep-2, output[6], math.floatEpsAt(f32, -0x1.0a65dep-2)); | |
| 564 | try testing.expectApproxEqAbs(-0x1.25046p-2, output[7], math.floatEpsAt(f32, -0x1.25046p-2)); | |
| 565 | try testing.expectApproxEqAbs(-0x1.6c6f0cp-1, output[8], math.floatEpsAt(f32, -0x1.6c6f0cp-1)); | |
| 566 | try testing.expectApproxEqAbs(0x1.350f7ap-1, output[9], math.floatEpsAt(f32, 0x1.350f7ap-1)); | |
| 567 | } | |
| 568 | ||
| 569 | test "asinBinary64Vec.special" { | |
| 570 | const input: @Vector(9, f64) = .{ | |
| 571 | 0x1p+0, | |
| 572 | -0x1p+0, | |
| 573 | 0x0p+0, | |
| 574 | -0x0p+0, | |
| 575 | 0x1.000002p+0, | |
| 576 | -0x1.000002p+0, | |
| 577 | math.inf(f64), | |
| 578 | -math.inf(f64), | |
| 579 | math.nan(f64), | |
| 580 | }; | |
| 581 | const output = asinBinary64Vec(9, input); | |
| 582 | try testing.expectApproxEqAbs(0x1.921fb54442d18p+0, output[0], math.floatEpsAt(f64, 0x1.921fb54442d18p+0)); | |
| 583 | try testing.expectApproxEqAbs(-0x1.921fb54442d18p+0, output[1], math.floatEpsAt(f64, -0x1.921fb54442d18p+0)); | |
| 584 | try testing.expectEqual(0x0p+0, output[2]); | |
| 585 | try testing.expectEqual(0x0p+0, output[3]); | |
| 586 | try testing.expect(math.isNan(output[4])); | |
| 587 | try testing.expect(math.isNan(output[5])); | |
| 588 | try testing.expect(math.isNan(output[6])); | |
| 589 | try testing.expect(math.isNan(output[7])); | |
| 590 | try testing.expect(math.isNan(output[8])); | |
| 591 | } | |
| 592 | ||
| 593 | test "asinBinary64Vec" { | |
| 594 | const input: @Vector(10, f64) = .{ | |
| 595 | 0x1.e674fba3e40d5p-2, | |
| 596 | -0x1.30fd0566fd979p-1, | |
| 597 | 0x1.6444a25abfeaap-2, | |
| 598 | 0x1.40a53228d1a13p-1, | |
| 599 | -0x1.ccc6d64845cfdp-1, | |
| 600 | -0x1.94bd91b7fc74bp-1, | |
| 601 | -0x1.8d741b5797fccp-2, | |
| 602 | -0x1.3e8e7e15881c5p-3, | |
| 603 | -0x1.88222d8ab8ca9p-2, | |
| 604 | -0x1.41c0e9babcbd2p-2, | |
| 605 | }; | |
| 606 | const output = asinBinary64Vec(10, input); | |
| 607 | try testing.expectApproxEqAbs(0x1.fae86c5941692p-2, output[0], math.floatEpsAt(f64, 0x1.fae86c5941692p-2)); | |
| 608 | try testing.expectApproxEqAbs(-0x1.46b6ad730c93ap-1, output[1], math.floatEpsAt(f64, -0x1.46b6ad730c93ap-1)); | |
| 609 | try testing.expectApproxEqAbs(0x1.6be0be8074eep-2, output[2], math.floatEpsAt(f64, 0x1.6be0be8074eep-2)); | |
| 610 | try testing.expectApproxEqAbs(0x1.5a7e98f53f717p-1, output[3], math.floatEpsAt(f64, 0x1.5a7e98f53f717p-1)); | |
| 611 | try testing.expectApproxEqAbs(-0x1.1ea2602d14e8p0, output[4], math.floatEpsAt(f64, -0x1.1ea2602d14e8p0)); | |
| 612 | try testing.expectApproxEqAbs(-0x1.d2c2634193158p-1, output[5], math.floatEpsAt(f64, -0x1.d2c2634193158p-1)); | |
| 613 | try testing.expectApproxEqAbs(-0x1.982d5f1895d2p-2, output[6], math.floatEpsAt(f64, -0x1.982d5f1895d2p-2)); | |
| 614 | try testing.expectApproxEqAbs(-0x1.3fdaf7dfdc864p-3, output[7], math.floatEpsAt(f64, -0x1.3fdaf7dfdc864p-3)); | |
| 615 | try testing.expectApproxEqAbs(-0x1.9269540735b7bp-2, output[8], math.floatEpsAt(f64, -0x1.9269540735b7bp-2)); | |
| 616 | try testing.expectApproxEqAbs(-0x1.474c4c6625527p-2, output[9], math.floatEpsAt(f64, -0x1.474c4c6625527p-2)); | |
| 617 | } |