| ... | ... | @@ -33,6 +33,24 @@ fn limbCount(bits: u16) u16 { |
| 33 | 33 | return @divExact(std.zig.target.intByteSize(&builtin.target, bits), 8); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | fn varLimbs(ptr: [*]u64, bits: u16) []u64 { |
| 37 | const limb_cnt = usedLimbCount(bits); |
| 38 | const true_limb_cnt = limbCount(bits); |
| 39 | return switch (endian) { |
| 40 | .little => ptr[0..limb_cnt], |
| 41 | .big => ptr[true_limb_cnt - limb_cnt .. true_limb_cnt], |
| 42 | }; |
| 43 | } |
| 44 | |
| 45 | fn constLimbs(ptr: [*]const u64, bits: u16) []const u64 { |
| 46 | const limb_cnt = usedLimbCount(bits); |
| 47 | const true_limb_cnt = limbCount(bits); |
| 48 | return switch (endian) { |
| 49 | .little => ptr[0..limb_cnt], |
| 50 | .big => ptr[true_limb_cnt - limb_cnt .. true_limb_cnt], |
| 51 | }; |
| 52 | } |
| 53 | |
| 36 | 54 | fn fixLastLimb(out_ptr: [*]u64, is_signed: bool, bits: u16) void { |
| 37 | 55 | const limb_cnt = usedLimbCount(bits); |
| 38 | 56 | const true_limb_cnt = limbCount(bits); |
| ... | ... | @@ -77,9 +95,9 @@ comptime { |
| 77 | 95 | |
| 78 | 96 | fn __addo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool { |
| 79 | 97 | const limb_cnt = usedLimbCount(bits); |
| 80 | | const out = out_ptr[0..limb_cnt]; |
| 81 | | const a = a_ptr[0..limb_cnt]; |
| 82 | | const b = b_ptr[0..limb_cnt]; |
| 98 | const out = varLimbs(out_ptr, bits); |
| 99 | const a = constLimbs(a_ptr, bits); |
| 100 | const b = constLimbs(b_ptr, bits); |
| 83 | 101 | |
| 84 | 102 | var carry: u1 = 0; |
| 85 | 103 | var i: usize = 0; |
| ... | ... | @@ -143,6 +161,9 @@ test __addo_limb64 { |
| 143 | 161 | try test__addo_limb64(i64, maxInt(i64), 1, .{ minInt(i64), true }); |
| 144 | 162 | try test__addo_limb64(i65, maxInt(i65), 1, .{ minInt(i65), true }); |
| 145 | 163 | try test__addo_limb64(i255, -3, 2, .{ -1, false }); |
| 164 | |
| 165 | try test__addo_limb64(u150, maxInt(u150), 2, .{ 1, true }); |
| 166 | try test__addo_limb64(i150, -3, 2, .{ -1, false }); |
| 146 | 167 | } |
| 147 | 168 | |
| 148 | 169 | comptime { |
| ... | ... | @@ -151,9 +172,9 @@ comptime { |
| 151 | 172 | |
| 152 | 173 | fn __subo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool { |
| 153 | 174 | const limb_cnt = usedLimbCount(bits); |
| 154 | | const out = out_ptr[0..limb_cnt]; |
| 155 | | const a = a_ptr[0..limb_cnt]; |
| 156 | | const b = b_ptr[0..limb_cnt]; |
| 175 | const out = varLimbs(out_ptr, bits); |
| 176 | const a = constLimbs(a_ptr, bits); |
| 177 | const b = constLimbs(b_ptr, bits); |
| 157 | 178 | |
| 158 | 179 | var borrow: u1 = 0; |
| 159 | 180 | var i: usize = 0; |
| ... | ... | @@ -216,6 +237,9 @@ test __subo_limb64 { |
| 216 | 237 | try test__subo_limb64(i64, minInt(i64), 1, .{ maxInt(i64), true }); |
| 217 | 238 | try test__subo_limb64(i65, minInt(i65), 1, .{ maxInt(i65), true }); |
| 218 | 239 | try test__subo_limb64(i255, -1, 2, .{ -3, false }); |
| 240 | |
| 241 | try test__subo_limb64(u150, 2, maxInt(u150), .{ 3, true }); |
| 242 | try test__subo_limb64(i150, -3, 2, .{ -5, false }); |
| 219 | 243 | } |
| 220 | 244 | |
| 221 | 245 | comptime { |
| ... | ... | @@ -227,8 +251,8 @@ comptime { |
| 227 | 251 | // a > b -> 1 |
| 228 | 252 | fn __cmp_limb64(a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) i8 { |
| 229 | 253 | const limb_cnt = usedLimbCount(bits); |
| 230 | | const a = a_ptr[0..limb_cnt]; |
| 231 | | const b = b_ptr[0..limb_cnt]; |
| 254 | const a = constLimbs(a_ptr, bits); |
| 255 | const b = constLimbs(b_ptr, bits); |
| 232 | 256 | |
| 233 | 257 | var i: usize = 0; |
| 234 | 258 | if (is_signed) { |
| ... | ... | @@ -284,6 +308,9 @@ test __cmp_limb64 { |
| 284 | 308 | try test__cmp_limb64(i255, -3, 2, -1); |
| 285 | 309 | try test__cmp_limb64(i255, -5, -5, 0); |
| 286 | 310 | try test__cmp_limb64(i255, 2, -3, 1); |
| 311 | |
| 312 | try test__cmp_limb64(u150, maxInt(u150) - 5, maxInt(u150) - 5, 0); |
| 313 | try test__cmp_limb64(i150, minInt(i150), -5, -1); |
| 287 | 314 | } |
| 288 | 315 | |
| 289 | 316 | comptime { |
| ... | ... | @@ -324,6 +351,9 @@ test __and_limb64 { |
| 324 | 351 | try test__and_limb64(i64, -1, 2, 2); |
| 325 | 352 | try test__and_limb64(i65, minInt(i65), -1, minInt(i65)); |
| 326 | 353 | try test__and_limb64(i255, -1, 2, 2); |
| 354 | |
| 355 | try test__and_limb64(u150, maxInt(u150), 7, 7); |
| 356 | try test__and_limb64(i150, -2, 3, 2); |
| 327 | 357 | } |
| 328 | 358 | |
| 329 | 359 | comptime { |
| ... | ... | @@ -364,6 +394,9 @@ test __or_limb64 { |
| 364 | 394 | try test__or_limb64(i64, -1, 2, -1); |
| 365 | 395 | try test__or_limb64(i65, minInt(i65), 1, minInt(i65) + 1); |
| 366 | 396 | try test__or_limb64(i255, -3, 2, -1); |
| 397 | |
| 398 | try test__or_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150)); |
| 399 | try test__or_limb64(i150, -2, 3, -1); |
| 367 | 400 | } |
| 368 | 401 | |
| 369 | 402 | comptime { |
| ... | ... | @@ -404,6 +437,9 @@ test __xor_limb64 { |
| 404 | 437 | try test__xor_limb64(i64, -1, 2, -3); |
| 405 | 438 | try test__xor_limb64(i65, minInt(i65), -1, maxInt(i65)); |
| 406 | 439 | try test__xor_limb64(i255, -3, 2, -1); |
| 440 | |
| 441 | try test__xor_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150) - 2); |
| 442 | try test__xor_limb64(i150, -2, 3, -3); |
| 407 | 443 | } |
| 408 | 444 | |
| 409 | 445 | comptime { |
| ... | ... | @@ -412,8 +448,8 @@ comptime { |
| 412 | 448 | |
| 413 | 449 | fn __not_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void { |
| 414 | 450 | const limb_cnt = usedLimbCount(bits); |
| 415 | | const out = out_ptr[0..limb_cnt]; |
| 416 | | const a = a_ptr[0..limb_cnt]; |
| 451 | const out = varLimbs(out_ptr, bits); |
| 452 | const a = constLimbs(a_ptr, bits); |
| 417 | 453 | |
| 418 | 454 | var i: usize = 0; |
| 419 | 455 | while (i < limb_cnt - 1) : (i += 1) { |
| ... | ... | @@ -450,6 +486,9 @@ test __not_limb64 { |
| 450 | 486 | try test__not_limb64(i64, -1, 0); |
| 451 | 487 | try test__not_limb64(i65, minInt(i65), maxInt(i65)); |
| 452 | 488 | try test__not_limb64(i255, -3, 2); |
| 489 | |
| 490 | try test__not_limb64(u150, maxInt(u150), 0); |
| 491 | try test__not_limb64(i150, maxInt(i150), minInt(i150)); |
| 453 | 492 | } |
| 454 | 493 | |
| 455 | 494 | comptime { |
| ... | ... | @@ -458,8 +497,8 @@ comptime { |
| 458 | 497 | |
| 459 | 498 | fn __shlo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) bool { |
| 460 | 499 | const limb_cnt = usedLimbCount(bits); |
| 461 | | const out = out_ptr[0..limb_cnt]; |
| 462 | | const a = a_ptr[0..limb_cnt]; |
| 500 | const out = varLimbs(out_ptr, bits); |
| 501 | const a = constLimbs(a_ptr, bits); |
| 463 | 502 | |
| 464 | 503 | assert(shift < bits); |
| 465 | 504 | |
| ... | ... | @@ -541,6 +580,9 @@ test __shlo_limb64 { |
| 541 | 580 | try test__shlo_limb64(i633, -1 << 299, 333, .{ -1 << 632, false }); |
| 542 | 581 | try test__shlo_limb64(i633, -1 << 300, 333, .{ 0, true }); |
| 543 | 582 | try test__shlo_limb64(i633, -1 << 298, 333, .{ -1 << 631, false }); |
| 583 | |
| 584 | try test__shlo_limb64(u150, maxInt(u150), 1, .{ maxInt(u150) - 1, true }); |
| 585 | try test__shlo_limb64(i150, -3, 1, .{ -6, false }); |
| 544 | 586 | } |
| 545 | 587 | |
| 546 | 588 | comptime { |
| ... | ... | @@ -549,8 +591,8 @@ comptime { |
| 549 | 591 | |
| 550 | 592 | fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) void { |
| 551 | 593 | const limb_cnt = usedLimbCount(bits); |
| 552 | | const out = out_ptr[0..limb_cnt]; |
| 553 | | const a = a_ptr[0..limb_cnt]; |
| 594 | const out = varLimbs(out_ptr, bits); |
| 595 | const a = constLimbs(a_ptr, bits); |
| 554 | 596 | |
| 555 | 597 | assert(shift < bits); |
| 556 | 598 | |
| ... | ... | @@ -572,6 +614,8 @@ fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: boo |
| 572 | 614 | carry = if (bit_shift != 0) (limb << @intCast(64 - bit_shift)) else 0; |
| 573 | 615 | } |
| 574 | 616 | } |
| 617 | |
| 618 | fixLastLimb(out_ptr, is_signed, bits); |
| 575 | 619 | } |
| 576 | 620 | |
| 577 | 621 | fn test__shr_limb64(comptime T: type, a: T, shift: u16, expected: T) !void { |
| ... | ... | @@ -609,6 +653,9 @@ test __shr_limb64 { |
| 609 | 653 | try test__shr_limb64(i633, -1 << 333, 333, -1); |
| 610 | 654 | try test__shr_limb64(i633, -1 << 334, 333, -2); |
| 611 | 655 | try test__shr_limb64(i633, -1 << 332, 333, -1); |
| 656 | |
| 657 | try test__shr_limb64(u150, maxInt(u150), 1, maxInt(u149)); |
| 658 | try test__shr_limb64(i150, -3, 1, -2); |
| 612 | 659 | } |
| 613 | 660 | |
| 614 | 661 | comptime { |
| ... | ... | @@ -617,7 +664,7 @@ comptime { |
| 617 | 664 | |
| 618 | 665 | fn __clz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 { |
| 619 | 666 | const limb_cnt = usedLimbCount(bits); |
| 620 | | const a = a_ptr[0..limb_cnt]; |
| 667 | const a = constLimbs(a_ptr, bits); |
| 621 | 668 | |
| 622 | 669 | var res: u16 = 0; |
| 623 | 670 | var i: usize = 0; |
| ... | ... | @@ -667,6 +714,9 @@ test __clz_limb64 { |
| 667 | 714 | try test__clz_limb64(i65, 1 << 32, 32); |
| 668 | 715 | try test__clz_limb64(i128, 0, 128); |
| 669 | 716 | try test__clz_limb64(i255, 1 << 130, 124); |
| 717 | |
| 718 | try test__clz_limb64(u150, 1 << 31, 118); |
| 719 | try test__clz_limb64(i150, maxInt(u65) - 1, 85); |
| 670 | 720 | } |
| 671 | 721 | |
| 672 | 722 | comptime { |
| ... | ... | @@ -675,7 +725,7 @@ comptime { |
| 675 | 725 | |
| 676 | 726 | fn __ctz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 { |
| 677 | 727 | const limb_cnt = usedLimbCount(bits); |
| 678 | | const a = a_ptr[0..limb_cnt]; |
| 728 | const a = constLimbs(a_ptr, bits); |
| 679 | 729 | |
| 680 | 730 | var res: u16 = 0; |
| 681 | 731 | var i: usize = 0; |
| ... | ... | @@ -720,6 +770,9 @@ test __ctz_limb64 { |
| 720 | 770 | try test__ctz_limb64(i65, 0, 65); |
| 721 | 771 | try test__ctz_limb64(i128, -1 << 73, 73); |
| 722 | 772 | try test__ctz_limb64(i255, 1 << 130, 130); |
| 773 | |
| 774 | try test__ctz_limb64(u150, 1 << 101, 101); |
| 775 | try test__ctz_limb64(i150, -1 << 74, 74); |
| 723 | 776 | } |
| 724 | 777 | |
| 725 | 778 | comptime { |
| ... | ... | @@ -728,7 +781,7 @@ comptime { |
| 728 | 781 | |
| 729 | 782 | fn __popcount_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 { |
| 730 | 783 | const limb_cnt = usedLimbCount(bits); |
| 731 | | const a = a_ptr[0..limb_cnt]; |
| 784 | const a = constLimbs(a_ptr, bits); |
| 732 | 785 | |
| 733 | 786 | var res: u16 = 0; |
| 734 | 787 | var i: usize = 0; |
| ... | ... | @@ -766,6 +819,9 @@ test __popcount_limb64 { |
| 766 | 819 | try test__popcount_limb64(i65, -1, 65); |
| 767 | 820 | try test__popcount_limb64(i128, -1 << 7, 121); |
| 768 | 821 | try test__popcount_limb64(i255, -1 << 200, 55); |
| 822 | |
| 823 | try test__popcount_limb64(u150, (1 << 149) | (1 << 65) | 1, 3); |
| 824 | try test__popcount_limb64(i150, -1 << 7, 143); |
| 769 | 825 | } |
| 770 | 826 | |
| 771 | 827 | comptime { |
| ... | ... | @@ -774,8 +830,8 @@ comptime { |
| 774 | 830 | |
| 775 | 831 | fn __bitreverse_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void { |
| 776 | 832 | const limb_cnt = usedLimbCount(bits); |
| 777 | | const out = out_ptr[0..limb_cnt]; |
| 778 | | const a = a_ptr[0..limb_cnt]; |
| 833 | const out = varLimbs(out_ptr, bits); |
| 834 | const a = constLimbs(a_ptr, bits); |
| 779 | 835 | |
| 780 | 836 | var i: usize = 0; |
| 781 | 837 | while (i < limb_cnt) : (i += 1) { |
| ... | ... | @@ -813,6 +869,9 @@ test __bitreverse_limb64 { |
| 813 | 869 | try test__bitreverse_limb64(i65, minInt(i65), 1); |
| 814 | 870 | try test__bitreverse_limb64(i128, 1 << 63, 1 << 64); |
| 815 | 871 | try test__bitreverse_limb64(i255, 1 << 130, 1 << 124); |
| 872 | |
| 873 | try test__bitreverse_limb64(u150, 1 << 9, 1 << 140); |
| 874 | try test__bitreverse_limb64(i150, minInt(i150), 1); |
| 816 | 875 | } |
| 817 | 876 | |
| 818 | 877 | comptime { |
| ... | ... | @@ -821,8 +880,8 @@ comptime { |
| 821 | 880 | |
| 822 | 881 | fn __byteswap_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void { |
| 823 | 882 | const limb_cnt = usedLimbCount(bits); |
| 824 | | const out = out_ptr[0..limb_cnt]; |
| 825 | | const a = a_ptr[0..limb_cnt]; |
| 883 | const out = varLimbs(out_ptr, bits); |
| 884 | const a = constLimbs(a_ptr, bits); |
| 826 | 885 | |
| 827 | 886 | assert(bits % 8 == 0); |
| 828 | 887 | |
| ... | ... | @@ -862,6 +921,9 @@ test __byteswap_limb64 { |
| 862 | 921 | try test__byteswap_limb64(i72, -1, -1); |
| 863 | 922 | try test__byteswap_limb64(i128, 1 << 56, 1 << 64); |
| 864 | 923 | try test__byteswap_limb64(i248, minInt(i248), 128); |
| 924 | |
| 925 | try test__byteswap_limb64(u152, 1, 1 << 144); |
| 926 | try test__byteswap_limb64(i152, 1 << 56, 1 << 88); |
| 865 | 927 | } |
| 866 | 928 | |
| 867 | 929 | comptime { |
| ... | ... | @@ -881,15 +943,19 @@ inline fn add3(x: *[3]u64, start: usize, v0: u64) void { |
| 881 | 943 | |
| 882 | 944 | fn mulwide(a: u64, b: u64) [2]u64 { |
| 883 | 945 | const muldXi = @import("mulXi3.zig").muldXi; |
| 884 | | return @bitCast(muldXi(u64, a, b)); |
| 946 | const limbs: [2]u64 = @bitCast(muldXi(u64, a, b)); |
| 947 | return switch (endian) { |
| 948 | .little => limbs, |
| 949 | .big => .{ limbs[1], limbs[0] }, |
| 950 | }; |
| 885 | 951 | } |
| 886 | 952 | |
| 887 | 953 | fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool { |
| 888 | 954 | const limb_cnt = usedLimbCount(bits); |
| 889 | 955 | |
| 890 | | const out = out_ptr[0..limb_cnt]; |
| 891 | | const a = a_ptr[0..limb_cnt]; |
| 892 | | const b = b_ptr[0..limb_cnt]; |
| 956 | const out = varLimbs(out_ptr, bits); |
| 957 | const a = constLimbs(a_ptr, bits); |
| 958 | const b = constLimbs(b_ptr, bits); |
| 893 | 959 | |
| 894 | 960 | @memset(out, 0); |
| 895 | 961 | |
| ... | ... | @@ -1002,6 +1068,9 @@ test __mulo_limb64 { |
| 1002 | 1068 | try test__mulo_limb64(i200, 1 << 100, 1 << 99, .{ minInt(i200), true }); |
| 1003 | 1069 | try test__mulo_limb64(i200, maxInt(i200), maxInt(i200), .{ 1, true }); |
| 1004 | 1070 | try test__mulo_limb64(i200, minInt(i200), minInt(i200), .{ 0, true }); |
| 1071 | |
| 1072 | try test__mulo_limb64(u150, maxInt(u150), 2, .{ maxInt(u150) - 1, true }); |
| 1073 | try test__mulo_limb64(i150, maxInt(i150), 2, .{ -2, true }); |
| 1005 | 1074 | } |
| 1006 | 1075 | |
| 1007 | 1076 | comptime { |
| ... | ... | @@ -1052,4 +1121,6 @@ test __abs_limb64 { |
| 1052 | 1121 | try test__abs_limb64(i200, -1 << 198, 1 << 198); |
| 1053 | 1122 | try test__abs_limb64(i255, -5, 5); |
| 1054 | 1123 | try test__abs_limb64(i255, minInt(i255), 1 << 254); |
| 1124 | |
| 1125 | try test__abs_limb64(i150, -40, 40); |
| 1055 | 1126 | } |