@zigc/lib 0.16.0 → 0.17.0-dev.135
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/c/fcntl.zig +6 -1
- package/c/inttypes.zig +0 -10
- package/c/math.zig +46 -122
- package/c/pthread.zig +57 -0
- package/c/search.zig +1 -27
- package/c/stdlib/drand48.zig +0 -57
- package/c/stdlib.zig +0 -100
- package/c/string.zig +20 -7
- package/c/strings.zig +0 -38
- package/c/unistd.zig +27 -26
- package/c/wchar.zig +10 -0
- package/c.zig +2 -2
- package/compiler/aro/aro/CodeGen.zig +5 -6
- package/compiler/aro/aro/Compilation.zig +17 -14
- package/compiler/aro/aro/Driver.zig +14 -13
- package/compiler/aro/aro/Parser.zig +20 -15
- package/compiler/aro/aro/Pragma.zig +3 -2
- package/compiler/aro/aro/Preprocessor.zig +9 -6
- package/compiler/aro/aro/pragmas/message.zig +3 -2
- package/compiler/aro/aro/text_literal.zig +3 -2
- package/compiler/aro/assembly_backend/x86_64.zig +4 -4
- package/compiler/build_runner.zig +0 -2
- package/compiler/reduce/Walk.zig +7 -7
- package/compiler/test_runner.zig +2 -2
- package/compiler/translate-c/Translator.zig +6 -2
- package/compiler/translate-c/main.zig +1 -1
- package/compiler_rt/cos.zig +0 -2
- package/compiler_rt/divmodei4.zig +40 -17
- package/compiler_rt/exp.zig +1 -6
- package/compiler_rt/exp2.zig +1 -6
- package/compiler_rt/exp_f128.zig +377 -0
- package/compiler_rt/fabs.zig +0 -2
- package/compiler_rt/fma.zig +0 -2
- package/compiler_rt/fmax.zig +0 -2
- package/compiler_rt/fmin.zig +0 -2
- package/compiler_rt/fmod.zig +0 -2
- package/compiler_rt/limb64.zig +876 -15
- package/compiler_rt/log.zig +0 -2
- package/compiler_rt/log10.zig +0 -2
- package/compiler_rt/log2.zig +0 -2
- package/compiler_rt/mulXi3.zig +1 -1
- package/compiler_rt/round.zig +0 -2
- package/compiler_rt/sin.zig +0 -2
- package/compiler_rt/sincos.zig +0 -2
- package/compiler_rt/sqrt.zig +0 -2
- package/compiler_rt/ssp.zig +1 -1
- package/compiler_rt/tan.zig +0 -2
- package/compiler_rt/trunc.zig +0 -2
- package/compiler_rt/udivmodei4.zig +28 -0
- package/fuzzer.zig +2 -0
- package/libc/include/aarch64-linux-any/asm/hwcap.h +1 -0
- package/libc/include/aarch64-linux-any/asm/unistd_64.h +1 -0
- package/libc/include/any-linux-any/asm-generic/errno.h +2 -0
- package/libc/include/any-linux-any/asm-generic/unistd.h +4 -1
- package/libc/include/any-linux-any/drm/amdgpu_drm.h +20 -6
- package/libc/include/any-linux-any/drm/amdxdna_accel.h +8 -0
- package/libc/include/any-linux-any/drm/drm_fourcc.h +6 -6
- package/libc/include/any-linux-any/drm/panfrost_drm.h +75 -1
- package/libc/include/any-linux-any/drm/panthor_drm.h +154 -3
- package/libc/include/any-linux-any/drm/rocket_accel.h +74 -24
- package/libc/include/any-linux-any/drm/xe_drm.h +89 -6
- package/libc/include/any-linux-any/linux/android/binder.h +1 -1
- package/libc/include/any-linux-any/linux/bpf.h +28 -0
- package/libc/include/any-linux-any/linux/btrfs.h +1 -0
- package/libc/include/any-linux-any/linux/btrfs_tree.h +32 -2
- package/libc/include/any-linux-any/linux/dma-buf.h +1 -0
- package/libc/include/any-linux-any/linux/dpll.h +1 -0
- package/libc/include/any-linux-any/linux/elf.h +2 -0
- package/libc/include/any-linux-any/linux/ethtool.h +21 -5
- package/libc/include/any-linux-any/linux/fs.h +1 -0
- package/libc/include/any-linux-any/linux/hyperv.h +1 -1
- package/libc/include/any-linux-any/linux/idxd.h +134 -134
- package/libc/include/any-linux-any/linux/if_alg.h +1 -1
- package/libc/include/any-linux-any/linux/if_link.h +1 -0
- package/libc/include/any-linux-any/linux/input-event-codes.h +4 -0
- package/libc/include/any-linux-any/linux/io_uring/bpf_filter.h +68 -0
- package/libc/include/any-linux-any/linux/io_uring/query.h +5 -1
- package/libc/include/any-linux-any/linux/io_uring.h +33 -2
- package/libc/include/any-linux-any/linux/iommufd.h +39 -0
- package/libc/include/any-linux-any/linux/kfd_ioctl.h +13 -3
- package/libc/include/any-linux-any/linux/kfd_sysfs.h +2 -1
- package/libc/include/any-linux-any/linux/kvm.h +30 -6
- package/libc/include/any-linux-any/linux/landlock.h +22 -8
- package/libc/include/any-linux-any/linux/magic.h +1 -0
- package/libc/include/any-linux-any/linux/mempolicy.h +3 -0
- package/libc/include/any-linux-any/linux/mount.h +11 -2
- package/libc/include/any-linux-any/linux/mptcp_pm.h +1 -1
- package/libc/include/any-linux-any/linux/mshv.h +2 -0
- package/libc/include/any-linux-any/linux/netfilter_bridge.h +5 -4
- package/libc/include/any-linux-any/linux/netfilter_ipv4.h +4 -5
- package/libc/include/any-linux-any/linux/netfilter_ipv6.h +3 -4
- package/libc/include/any-linux-any/linux/nfs.h +1 -1
- package/libc/include/any-linux-any/linux/nfsd_netlink.h +1 -0
- package/libc/include/any-linux-any/linux/nilfs2_api.h +2 -2
- package/libc/include/any-linux-any/linux/nilfs2_ondisk.h +97 -66
- package/libc/include/any-linux-any/linux/nl80211.h +104 -3
- package/libc/include/any-linux-any/linux/pci.h +7 -0
- package/libc/include/any-linux-any/linux/pci_regs.h +65 -6
- package/libc/include/any-linux-any/linux/pcitest.h +1 -0
- package/libc/include/any-linux-any/linux/perf_event.h +24 -3
- package/libc/include/any-linux-any/linux/pkt_sched.h +1 -0
- package/libc/include/any-linux-any/linux/prctl.h +30 -0
- package/libc/include/any-linux-any/linux/rseq.h +62 -5
- package/libc/include/any-linux-any/linux/shm.h +0 -1
- package/libc/include/any-linux-any/linux/stddef.h +4 -0
- package/libc/include/any-linux-any/linux/sysctl.h +1 -2
- package/libc/include/any-linux-any/linux/taskstats.h +12 -1
- package/libc/include/any-linux-any/linux/tcp.h +23 -3
- package/libc/include/any-linux-any/linux/typelimits.h +8 -0
- package/libc/include/any-linux-any/linux/ublk_cmd.h +120 -1
- package/libc/include/any-linux-any/linux/v4l2-controls.h +63 -0
- package/libc/include/any-linux-any/linux/vbox_vmmdev_types.h +2 -2
- package/libc/include/any-linux-any/linux/vduse.h +80 -5
- package/libc/include/any-linux-any/linux/version.h +3 -3
- package/libc/include/any-linux-any/linux/vfio.h +4 -0
- package/libc/include/any-linux-any/linux/videodev2.h +3 -0
- package/libc/include/any-linux-any/linux/virtio_ring.h +1 -2
- package/libc/include/any-linux-any/linux/vmclock-abi.h +20 -0
- package/libc/include/any-linux-any/rdma/bnxt_re-abi.h +16 -0
- package/libc/include/any-linux-any/rdma/ib_user_ioctl_cmds.h +16 -0
- package/libc/include/any-linux-any/rdma/mana-abi.h +3 -0
- package/libc/include/any-linux-any/scsi/scsi_bsg_ufs.h +8 -9
- package/libc/include/any-linux-any/sound/sof/tokens.h +6 -0
- package/libc/include/arc-linux-any/asm/swab.h +0 -63
- package/libc/include/arc-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/arm-linux-any/asm/ptrace.h +0 -9
- package/libc/include/arm-linux-any/asm/unistd-eabi.h +1 -0
- package/libc/include/arm-linux-any/asm/unistd-oabi.h +1 -0
- package/libc/include/csky-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/hexagon-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/loongarch-linux-any/asm/hwcap.h +1 -0
- package/libc/include/loongarch-linux-any/asm/kvm.h +1 -0
- package/libc/include/loongarch-linux-any/asm/kvm_para.h +1 -0
- package/libc/include/loongarch-linux-any/asm/unistd_32.h +2 -0
- package/libc/include/loongarch-linux-any/asm/unistd_64.h +2 -0
- package/libc/include/m68k-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/mips-linux-any/asm/errno.h +2 -0
- package/libc/include/mips-linux-any/asm/unistd_n32.h +1 -0
- package/libc/include/mips-linux-any/asm/unistd_n64.h +1 -0
- package/libc/include/mips-linux-any/asm/unistd_o32.h +1 -0
- package/libc/include/powerpc-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/powerpc-linux-any/asm/unistd_64.h +1 -0
- package/libc/include/riscv-linux-any/asm/hwprobe.h +4 -0
- package/libc/include/riscv-linux-any/asm/kvm.h +3 -0
- package/libc/include/riscv-linux-any/asm/ptrace.h +37 -0
- package/libc/include/riscv-linux-any/asm/sigcontext.h +1 -0
- package/libc/include/riscv-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/riscv-linux-any/asm/unistd_64.h +1 -0
- package/libc/include/s390x-linux-any/asm/unistd_64.h +1 -0
- package/libc/include/sparc-linux-any/asm/errno.h +2 -0
- package/libc/include/sparc-linux-any/asm/ioctls.h +4 -4
- package/libc/include/sparc-linux-any/asm/unistd_32.h +2 -0
- package/libc/include/sparc-linux-any/asm/unistd_64.h +2 -0
- package/libc/include/x86-linux-any/asm/auxvec.h +0 -4
- package/libc/include/x86-linux-any/asm/kvm.h +13 -8
- package/libc/include/x86-linux-any/asm/svm.h +16 -16
- package/libc/include/x86-linux-any/asm/unistd_32.h +1 -0
- package/libc/include/x86-linux-any/asm/unistd_64.h +1 -0
- package/libc/include/x86-linux-any/asm/unistd_x32.h +1 -0
- package/libc/include/xtensa-linux-any/asm/unistd_32.h +1 -0
- package/libc/musl/arch/mipsn32/syscall_arch.h +35 -32
- package/package.json +1 -1
- package/std/Build/Cache.zig +6 -6
- package/std/Build/Step/Compile.zig +0 -1
- package/std/Build/Step/Run.zig +2 -2
- package/std/Build/Step.zig +2 -4
- package/std/Build/WebServer.zig +2 -2
- package/std/Build.zig +0 -3
- package/std/Io/Dir.zig +7 -2
- package/std/Io/Dispatch.zig +3 -13
- package/std/Io/File/Writer.zig +8 -6
- package/std/Io/Reader.zig +8 -9
- package/std/Io/Semaphore.zig +112 -17
- package/std/Io/Terminal.zig +1 -1
- package/std/Io/Threaded.zig +171 -37
- package/std/Io/Uring.zig +13 -15
- package/std/Io/Writer.zig +46 -42
- package/std/Io/net.zig +11 -11
- package/std/Io.zig +90 -26
- package/std/SemanticVersion.zig +1 -1
- package/std/Target/Query.zig +2 -2
- package/std/Target.zig +50 -5
- package/std/array_hash_map.zig +9 -18
- package/std/builtin.zig +4 -0
- package/std/c/haiku.zig +3 -0
- package/std/c/serenity.zig +1 -6
- package/std/c.zig +89 -7
- package/std/compress/flate/Decompress.zig +2 -3
- package/std/compress/zstd/Decompress.zig +2 -4
- package/std/crypto/Certificate.zig +13 -1
- package/std/crypto/ascon.zig +75 -33
- package/std/crypto/codecs/asn1/Oid.zig +12 -1
- package/std/crypto/codecs/base64_hex_ct.zig +2 -4
- package/std/crypto/ml_kem.zig +2 -9
- package/std/crypto/tls/Client.zig +79 -4
- package/std/crypto/tls.zig +1 -1
- package/std/crypto.zig +1 -0
- package/std/debug/Pdb.zig +1 -1
- package/std/debug.zig +4 -3
- package/std/fmt.zig +8 -3
- package/std/fs/path.zig +6 -4
- package/std/heap/BufferFirstAllocator.zig +165 -0
- package/std/heap.zig +2 -126
- package/std/http/Client.zig +21 -24
- package/std/http.zig +3 -4
- package/std/json/Scanner.zig +2 -2
- package/std/os/emscripten.zig +1 -1
- package/std/os/linux/IoUring.zig +2 -0
- package/std/os/linux/aarch64.zig +41 -12
- package/std/os/linux/arc.zig +173 -0
- package/std/os/linux/arm.zig +41 -12
- package/std/os/linux/hexagon.zig +33 -11
- package/std/os/linux/loongarch32.zig +41 -13
- package/std/os/linux/loongarch64.zig +41 -12
- package/std/os/linux/m68k.zig +41 -13
- package/std/os/linux/mips.zig +67 -36
- package/std/os/linux/mips64.zig +60 -29
- package/std/os/linux/mipsn32.zig +60 -29
- package/std/os/linux/or1k.zig +41 -12
- package/std/os/linux/powerpc.zig +41 -12
- package/std/os/linux/powerpc64.zig +41 -12
- package/std/os/linux/riscv32.zig +41 -12
- package/std/os/linux/riscv64.zig +41 -12
- package/std/os/linux/s390x.zig +44 -7
- package/std/os/linux/sparc64.zig +83 -52
- package/std/os/linux/syscalls.zig +26 -1
- package/std/os/linux/thumb.zig +52 -36
- package/std/os/linux/x32.zig +41 -12
- package/std/os/linux/x86.zig +42 -13
- package/std/os/linux/x86_64.zig +41 -12
- package/std/os/linux.zig +412 -436
- package/std/os/uefi/tables/boot_services.zig +9 -8
- package/std/os.zig +41 -0
- package/std/process.zig +1 -1
- package/std/sort.zig +3 -3
- package/std/zig/Ast/Render.zig +3 -3
- package/std/zig/AstGen.zig +44 -98
- package/std/zig/AstRlAnnotate.zig +0 -11
- package/std/zig/BuiltinFn.zig +0 -32
- package/std/zig/LibCInstallation.zig +4 -3
- package/std/zig/Parse.zig +7 -7
- package/std/zig/WindowsSdk.zig +13 -13
- package/std/zig/Zir.zig +50 -63
- package/std/zig/ZonGen.zig +6 -5
- package/std/zig/llvm/Builder.zig +12 -12
- package/std/zig.zig +1 -10
- package/std/zip.zig +5 -5
- package/zig.h +340 -1
- package/libc/include/hexagon-linux-any/asm/signal.h +0 -29
- package/libc/include/s390x-linux-any/asm/tape390.h +0 -103
- package/libc/mingw/math/fdiml.c +0 -24
- package/libc/mingw/winpthreads/spinlock.c +0 -82
- package/libc/musl/src/linux/tee.c +0 -8
- package/libc/musl/src/math/fdimf.c +0 -10
- package/libc/musl/src/math/fdiml.c +0 -18
- package/libc/musl/src/string/strdup.c +0 -10
- package/libc/musl/src/string/strndup.c +0 -12
- package/libc/musl/src/string/wcsdup.c +0 -10
- package/libc/musl/src/thread/pthread_spin_destroy.c +0 -6
- package/libc/musl/src/thread/pthread_spin_init.c +0 -6
- package/libc/musl/src/thread/pthread_spin_lock.c +0 -8
- package/libc/musl/src/thread/pthread_spin_trylock.c +0 -7
- package/libc/musl/src/thread/pthread_spin_unlock.c +0 -7
- package/libc/musl/src/unistd/dup2.c +0 -20
- package/libc/musl/src/unistd/dup3.c +0 -26
- package/libc/wasi/thread-stub/pthread_spin_lock.c +0 -8
- package/libc/wasi/thread-stub/pthread_spin_trylock.c +0 -8
- package/libc/wasi/thread-stub/pthread_spin_unlock.c +0 -7
package/compiler_rt/limb64.zig
CHANGED
|
@@ -7,6 +7,7 @@ const divCeil = std.math.divCeil;
|
|
|
7
7
|
|
|
8
8
|
const builtin = @import("builtin");
|
|
9
9
|
const compiler_rt = @import("../compiler_rt.zig");
|
|
10
|
+
const symbol = @import("../compiler_rt.zig").symbol;
|
|
10
11
|
|
|
11
12
|
const endian = builtin.cpu.arch.endian();
|
|
12
13
|
|
|
@@ -24,10 +25,45 @@ inline fn limbSet(limbs: []u64, i: usize, value: u64) void {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
fn
|
|
28
|
+
fn usedLimbCount(bits: u16) u16 {
|
|
28
29
|
return divCeil(u16, bits, 64) catch unreachable;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
fn limbCount(bits: u16) u16 {
|
|
33
|
+
return @divExact(std.zig.target.intByteSize(&builtin.target, bits), 8);
|
|
34
|
+
}
|
|
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
|
+
|
|
54
|
+
fn fixLastLimb(out_ptr: [*]u64, is_signed: bool, bits: u16) void {
|
|
55
|
+
const limb_cnt = usedLimbCount(bits);
|
|
56
|
+
const true_limb_cnt = limbCount(bits);
|
|
57
|
+
if (limb_cnt == true_limb_cnt) return;
|
|
58
|
+
const true_out = out_ptr[0..true_limb_cnt];
|
|
59
|
+
|
|
60
|
+
const ms = limbGet(true_out, limb_cnt - 1);
|
|
61
|
+
const sign: u64 = if (!is_signed or @as(i64, @bitCast(ms)) >= 0) 0 else ~@as(u64, 0);
|
|
62
|
+
for (limb_cnt..true_limb_cnt) |i| {
|
|
63
|
+
limbSet(true_out, i, sign);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
31
67
|
fn Limbs(T: type) type {
|
|
32
68
|
const int_info = @typeInfo(T).int;
|
|
33
69
|
const limb_cnt = comptime limbCount(int_info.bits);
|
|
@@ -55,14 +91,14 @@ fn limbWrap(limb: u64, is_signed: bool, bits: u16) u64 {
|
|
|
55
91
|
}
|
|
56
92
|
|
|
57
93
|
comptime {
|
|
58
|
-
|
|
94
|
+
symbol(&__addo_limb64, "__addo_limb64");
|
|
59
95
|
}
|
|
60
96
|
|
|
61
97
|
fn __addo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
|
|
62
|
-
const limb_cnt =
|
|
63
|
-
const out = out_ptr
|
|
64
|
-
const a = a_ptr
|
|
65
|
-
const b = b_ptr
|
|
98
|
+
const limb_cnt = usedLimbCount(bits);
|
|
99
|
+
const out = varLimbs(out_ptr, bits);
|
|
100
|
+
const a = constLimbs(a_ptr, bits);
|
|
101
|
+
const b = constLimbs(b_ptr, bits);
|
|
66
102
|
|
|
67
103
|
var carry: u1 = 0;
|
|
68
104
|
var i: usize = 0;
|
|
@@ -91,11 +127,13 @@ fn __addo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_s
|
|
|
91
127
|
|
|
92
128
|
if (bits % 64 == 0) {
|
|
93
129
|
limbSet(out, i, limb);
|
|
130
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
94
131
|
return carry != 0;
|
|
95
132
|
} else {
|
|
96
133
|
assert(carry == 0);
|
|
97
134
|
const wrapped_limb = limbWrap(limb, is_signed, bits);
|
|
98
135
|
limbSet(out, i, wrapped_limb);
|
|
136
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
99
137
|
return wrapped_limb != limb;
|
|
100
138
|
}
|
|
101
139
|
}
|
|
@@ -124,17 +162,20 @@ test __addo_limb64 {
|
|
|
124
162
|
try test__addo_limb64(i64, maxInt(i64), 1, .{ minInt(i64), true });
|
|
125
163
|
try test__addo_limb64(i65, maxInt(i65), 1, .{ minInt(i65), true });
|
|
126
164
|
try test__addo_limb64(i255, -3, 2, .{ -1, false });
|
|
165
|
+
|
|
166
|
+
try test__addo_limb64(u150, maxInt(u150), 2, .{ 1, true });
|
|
167
|
+
try test__addo_limb64(i150, -3, 2, .{ -1, false });
|
|
127
168
|
}
|
|
128
169
|
|
|
129
170
|
comptime {
|
|
130
|
-
|
|
171
|
+
symbol(&__subo_limb64, "__subo_limb64");
|
|
131
172
|
}
|
|
132
173
|
|
|
133
174
|
fn __subo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
|
|
134
|
-
const limb_cnt =
|
|
135
|
-
const out = out_ptr
|
|
136
|
-
const a = a_ptr
|
|
137
|
-
const b = b_ptr
|
|
175
|
+
const limb_cnt = usedLimbCount(bits);
|
|
176
|
+
const out = varLimbs(out_ptr, bits);
|
|
177
|
+
const a = constLimbs(a_ptr, bits);
|
|
178
|
+
const b = constLimbs(b_ptr, bits);
|
|
138
179
|
|
|
139
180
|
var borrow: u1 = 0;
|
|
140
181
|
var i: usize = 0;
|
|
@@ -163,10 +204,12 @@ fn __subo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_s
|
|
|
163
204
|
|
|
164
205
|
if (bits % 64 == 0) {
|
|
165
206
|
limbSet(out, i, limb);
|
|
207
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
166
208
|
return borrow != 0;
|
|
167
209
|
} else {
|
|
168
210
|
const wrapped_limb = limbWrap(limb, is_signed, bits);
|
|
169
211
|
limbSet(out, i, wrapped_limb);
|
|
212
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
170
213
|
return borrow != 0 or wrapped_limb != limb;
|
|
171
214
|
}
|
|
172
215
|
}
|
|
@@ -195,19 +238,22 @@ test __subo_limb64 {
|
|
|
195
238
|
try test__subo_limb64(i64, minInt(i64), 1, .{ maxInt(i64), true });
|
|
196
239
|
try test__subo_limb64(i65, minInt(i65), 1, .{ maxInt(i65), true });
|
|
197
240
|
try test__subo_limb64(i255, -1, 2, .{ -3, false });
|
|
241
|
+
|
|
242
|
+
try test__subo_limb64(u150, 2, maxInt(u150), .{ 3, true });
|
|
243
|
+
try test__subo_limb64(i150, -3, 2, .{ -5, false });
|
|
198
244
|
}
|
|
199
245
|
|
|
200
246
|
comptime {
|
|
201
|
-
|
|
247
|
+
symbol(&__cmp_limb64, "__cmp_limb64");
|
|
202
248
|
}
|
|
203
249
|
|
|
204
250
|
// a < b -> -1
|
|
205
251
|
// a == b -> 0
|
|
206
252
|
// a > b -> 1
|
|
207
253
|
fn __cmp_limb64(a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) i8 {
|
|
208
|
-
const limb_cnt =
|
|
209
|
-
const a = a_ptr
|
|
210
|
-
const b = b_ptr
|
|
254
|
+
const limb_cnt = usedLimbCount(bits);
|
|
255
|
+
const a = constLimbs(a_ptr, bits);
|
|
256
|
+
const b = constLimbs(b_ptr, bits);
|
|
211
257
|
|
|
212
258
|
var i: usize = 0;
|
|
213
259
|
if (is_signed) {
|
|
@@ -263,4 +309,819 @@ test __cmp_limb64 {
|
|
|
263
309
|
try test__cmp_limb64(i255, -3, 2, -1);
|
|
264
310
|
try test__cmp_limb64(i255, -5, -5, 0);
|
|
265
311
|
try test__cmp_limb64(i255, 2, -3, 1);
|
|
312
|
+
|
|
313
|
+
try test__cmp_limb64(u150, maxInt(u150) - 5, maxInt(u150) - 5, 0);
|
|
314
|
+
try test__cmp_limb64(i150, minInt(i150), -5, -1);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
comptime {
|
|
318
|
+
symbol(&__and_limb64, "__and_limb64");
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fn __and_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, bits: u16) callconv(.c) void {
|
|
322
|
+
const limb_cnt = limbCount(bits);
|
|
323
|
+
const out = out_ptr[0..limb_cnt];
|
|
324
|
+
const a = a_ptr[0..limb_cnt];
|
|
325
|
+
const b = b_ptr[0..limb_cnt];
|
|
326
|
+
|
|
327
|
+
var i: usize = 0;
|
|
328
|
+
while (i < limb_cnt) : (i += 1) {
|
|
329
|
+
limbSet(out, i, limbGet(a, i) & limbGet(b, i));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fn test__and_limb64(comptime T: type, a: T, b: T, expected: T) !void {
|
|
334
|
+
const int_info = @typeInfo(T).int;
|
|
335
|
+
|
|
336
|
+
var a_limbs = asLimbs(a);
|
|
337
|
+
var b_limbs = asLimbs(b);
|
|
338
|
+
var out: Limbs(T) = undefined;
|
|
339
|
+
__and_limb64(&out, &a_limbs, &b_limbs, int_info.bits);
|
|
340
|
+
|
|
341
|
+
const expected_limbs = asLimbs(expected);
|
|
342
|
+
try testing.expectEqual(expected_limbs, out);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
test __and_limb64 {
|
|
346
|
+
try test__and_limb64(u64, 1, 2, 0);
|
|
347
|
+
try test__and_limb64(u64, maxInt(u64), 2, 2);
|
|
348
|
+
try test__and_limb64(u65, maxInt(u65), 2, 2);
|
|
349
|
+
try test__and_limb64(u255, maxInt(u255), 7, 7);
|
|
350
|
+
|
|
351
|
+
try test__and_limb64(i64, 1, 2, 0);
|
|
352
|
+
try test__and_limb64(i64, -1, 2, 2);
|
|
353
|
+
try test__and_limb64(i65, minInt(i65), -1, minInt(i65));
|
|
354
|
+
try test__and_limb64(i255, -1, 2, 2);
|
|
355
|
+
|
|
356
|
+
try test__and_limb64(u150, maxInt(u150), 7, 7);
|
|
357
|
+
try test__and_limb64(i150, -2, 3, 2);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
comptime {
|
|
361
|
+
symbol(&__or_limb64, "__or_limb64");
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
fn __or_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, bits: u16) callconv(.c) void {
|
|
365
|
+
const limb_cnt = limbCount(bits);
|
|
366
|
+
const out = out_ptr[0..limb_cnt];
|
|
367
|
+
const a = a_ptr[0..limb_cnt];
|
|
368
|
+
const b = b_ptr[0..limb_cnt];
|
|
369
|
+
|
|
370
|
+
var i: usize = 0;
|
|
371
|
+
while (i < limb_cnt) : (i += 1) {
|
|
372
|
+
limbSet(out, i, limbGet(a, i) | limbGet(b, i));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
fn test__or_limb64(comptime T: type, a: T, b: T, expected: T) !void {
|
|
377
|
+
const int_info = @typeInfo(T).int;
|
|
378
|
+
|
|
379
|
+
var a_limbs = asLimbs(a);
|
|
380
|
+
var b_limbs = asLimbs(b);
|
|
381
|
+
var out: Limbs(T) = undefined;
|
|
382
|
+
__or_limb64(&out, &a_limbs, &b_limbs, int_info.bits);
|
|
383
|
+
|
|
384
|
+
const expected_limbs = asLimbs(expected);
|
|
385
|
+
try testing.expectEqual(expected_limbs, out);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
test __or_limb64 {
|
|
389
|
+
try test__or_limb64(u64, 1, 2, 3);
|
|
390
|
+
try test__or_limb64(u64, maxInt(u64), 2, maxInt(u64));
|
|
391
|
+
try test__or_limb64(u65, maxInt(u65), 2, maxInt(u65));
|
|
392
|
+
try test__or_limb64(u255, 1, 2, 3);
|
|
393
|
+
|
|
394
|
+
try test__or_limb64(i64, 1, 2, 3);
|
|
395
|
+
try test__or_limb64(i64, -1, 2, -1);
|
|
396
|
+
try test__or_limb64(i65, minInt(i65), 1, minInt(i65) + 1);
|
|
397
|
+
try test__or_limb64(i255, -3, 2, -1);
|
|
398
|
+
|
|
399
|
+
try test__or_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150));
|
|
400
|
+
try test__or_limb64(i150, -2, 3, -1);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
comptime {
|
|
404
|
+
symbol(&__xor_limb64, "__xor_limb64");
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
fn __xor_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, bits: u16) callconv(.c) void {
|
|
408
|
+
const limb_cnt = limbCount(bits);
|
|
409
|
+
const out = out_ptr[0..limb_cnt];
|
|
410
|
+
const a = a_ptr[0..limb_cnt];
|
|
411
|
+
const b = b_ptr[0..limb_cnt];
|
|
412
|
+
|
|
413
|
+
var i: usize = 0;
|
|
414
|
+
while (i < limb_cnt) : (i += 1) {
|
|
415
|
+
limbSet(out, i, limbGet(a, i) ^ limbGet(b, i));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
fn test__xor_limb64(comptime T: type, a: T, b: T, expected: T) !void {
|
|
420
|
+
const int_info = @typeInfo(T).int;
|
|
421
|
+
|
|
422
|
+
var a_limbs = asLimbs(a);
|
|
423
|
+
var b_limbs = asLimbs(b);
|
|
424
|
+
var out: Limbs(T) = undefined;
|
|
425
|
+
__xor_limb64(&out, &a_limbs, &b_limbs, int_info.bits);
|
|
426
|
+
|
|
427
|
+
const expected_limbs = asLimbs(expected);
|
|
428
|
+
try testing.expectEqual(expected_limbs, out);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
test __xor_limb64 {
|
|
432
|
+
try test__xor_limb64(u64, 1, 2, 3);
|
|
433
|
+
try test__xor_limb64(u64, 3, 2, 1);
|
|
434
|
+
try test__xor_limb64(u65, maxInt(u65), 2, maxInt(u65) - 2);
|
|
435
|
+
try test__xor_limb64(u255, 7, 3, 4);
|
|
436
|
+
|
|
437
|
+
try test__xor_limb64(i64, 3, 2, 1);
|
|
438
|
+
try test__xor_limb64(i64, -1, 2, -3);
|
|
439
|
+
try test__xor_limb64(i65, minInt(i65), -1, maxInt(i65));
|
|
440
|
+
try test__xor_limb64(i255, -3, 2, -1);
|
|
441
|
+
|
|
442
|
+
try test__xor_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150) - 2);
|
|
443
|
+
try test__xor_limb64(i150, -2, 3, -3);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
comptime {
|
|
447
|
+
symbol(&__not_limb64, "__not_limb64");
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
fn __not_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
|
|
451
|
+
const limb_cnt = usedLimbCount(bits);
|
|
452
|
+
const out = varLimbs(out_ptr, bits);
|
|
453
|
+
const a = constLimbs(a_ptr, bits);
|
|
454
|
+
|
|
455
|
+
var i: usize = 0;
|
|
456
|
+
while (i < limb_cnt - 1) : (i += 1) {
|
|
457
|
+
limbSet(out, i, ~limbGet(a, i));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
var limb: u64 = ~limbGet(a, i);
|
|
461
|
+
if (!is_signed and bits % 64 != 0) {
|
|
462
|
+
limb = limbWrap(limb, is_signed, bits);
|
|
463
|
+
}
|
|
464
|
+
limbSet(out, i, limb);
|
|
465
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
fn test__not_limb64(comptime T: type, a: T, expected: T) !void {
|
|
469
|
+
const int_info = @typeInfo(T).int;
|
|
470
|
+
const is_signed = int_info.signedness == .signed;
|
|
471
|
+
|
|
472
|
+
var a_limbs = asLimbs(a);
|
|
473
|
+
var out: Limbs(T) = undefined;
|
|
474
|
+
__not_limb64(&out, &a_limbs, is_signed, int_info.bits);
|
|
475
|
+
|
|
476
|
+
const expected_limbs = asLimbs(expected);
|
|
477
|
+
try testing.expectEqual(expected_limbs, out);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
test __not_limb64 {
|
|
481
|
+
try test__not_limb64(u64, 1, maxInt(u64) - 1);
|
|
482
|
+
try test__not_limb64(u64, 3, maxInt(u64) - 3);
|
|
483
|
+
try test__not_limb64(u65, maxInt(u65), 0);
|
|
484
|
+
try test__not_limb64(u255, 7, maxInt(u255) - 7);
|
|
485
|
+
|
|
486
|
+
try test__not_limb64(i64, 3, -4);
|
|
487
|
+
try test__not_limb64(i64, -1, 0);
|
|
488
|
+
try test__not_limb64(i65, minInt(i65), maxInt(i65));
|
|
489
|
+
try test__not_limb64(i255, -3, 2);
|
|
490
|
+
|
|
491
|
+
try test__not_limb64(u150, maxInt(u150), 0);
|
|
492
|
+
try test__not_limb64(i150, maxInt(i150), minInt(i150));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
comptime {
|
|
496
|
+
symbol(&__shlo_limb64, "__shlo_limb64");
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
fn __shlo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) bool {
|
|
500
|
+
const limb_cnt = usedLimbCount(bits);
|
|
501
|
+
const out = varLimbs(out_ptr, bits);
|
|
502
|
+
const a = constLimbs(a_ptr, bits);
|
|
503
|
+
|
|
504
|
+
assert(shift < bits);
|
|
505
|
+
|
|
506
|
+
const limb_shift = shift / 64;
|
|
507
|
+
const bit_shift = shift % 64;
|
|
508
|
+
|
|
509
|
+
var carry: u64 = 0;
|
|
510
|
+
var i: usize = 0;
|
|
511
|
+
while (i < limb_cnt - 1) : (i += 1) {
|
|
512
|
+
if (i < limb_shift) {
|
|
513
|
+
limbSet(out, i, 0);
|
|
514
|
+
} else {
|
|
515
|
+
const limb = limbGet(a, i - limb_shift);
|
|
516
|
+
limbSet(out, i, (limb << @intCast(bit_shift)) | carry);
|
|
517
|
+
carry = if (bit_shift != 0) (limb >> @intCast(64 - bit_shift)) else 0;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const limb = limbGet(a, i - limb_shift);
|
|
522
|
+
const raw_last = (limb << @intCast(bit_shift)) | carry;
|
|
523
|
+
carry = if (bit_shift != 0) (limb >> @intCast(64 - bit_shift)) else 0;
|
|
524
|
+
|
|
525
|
+
const last = if (bits % 64 == 0) raw_last else limbWrap(raw_last, is_signed, bits);
|
|
526
|
+
limbSet(out, i, last);
|
|
527
|
+
|
|
528
|
+
const sign_extend: u64 = if (is_signed and (last >> 63) == 1) ~@as(u64, 0) else 0;
|
|
529
|
+
const expected_carry: u64 = if (bit_shift == 0) 0 else sign_extend >> @intCast(64 - bit_shift);
|
|
530
|
+
|
|
531
|
+
var overflow = carry != expected_carry;
|
|
532
|
+
if (bits % 64 != 0) {
|
|
533
|
+
overflow = overflow or raw_last != last;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
var j = limb_cnt - limb_shift;
|
|
537
|
+
while (j < limb_cnt) : (j += 1) {
|
|
538
|
+
overflow = overflow or limbGet(a, j) != sign_extend;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
542
|
+
return overflow;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
fn test__shlo_limb64(comptime T: type, a: T, shift: u16, expected: struct { T, bool }) !void {
|
|
546
|
+
const int_info = @typeInfo(T).int;
|
|
547
|
+
const is_signed = int_info.signedness == .signed;
|
|
548
|
+
|
|
549
|
+
var a_limbs = asLimbs(a);
|
|
550
|
+
var out: Limbs(T) = undefined;
|
|
551
|
+
const overflow = __shlo_limb64(&out, &a_limbs, shift, is_signed, int_info.bits);
|
|
552
|
+
|
|
553
|
+
const expected_limbs = asLimbs(expected[0]);
|
|
554
|
+
try testing.expectEqual(expected_limbs, out);
|
|
555
|
+
try testing.expectEqual(expected[1], overflow);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
test __shlo_limb64 {
|
|
559
|
+
try test__shlo_limb64(u64, 0x1234_5678_9ABC_DEF0, 4, .{ 0x2345_6789_ABCD_EF00, true });
|
|
560
|
+
try test__shlo_limb64(u64, 0x8000_0000_0000_0001, 63, .{ 0x8000_0000_0000_0000, true });
|
|
561
|
+
try test__shlo_limb64(u65, 1, 64, .{ 0x1_0000_0000_0000_0000, false });
|
|
562
|
+
try test__shlo_limb64(u65, 0x1_0000_0000_0000_0000, 1, .{ 0, true });
|
|
563
|
+
try test__shlo_limb64(u128, 0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0, 4, .{ 0x2345_6789_ABCD_EF01_2345_6789_ABCD_EF00, true });
|
|
564
|
+
try test__shlo_limb64(u255, maxInt(u255), 1, .{ maxInt(u255) - 1, true });
|
|
565
|
+
try test__shlo_limb64(u633, 1 << 299, 333, .{ 1 << 632, false });
|
|
566
|
+
try test__shlo_limb64(u633, 1 << 300, 333, .{ 0, true });
|
|
567
|
+
try test__shlo_limb64(u633, 1 << 298, 333, .{ 1 << 631, false });
|
|
568
|
+
|
|
569
|
+
try test__shlo_limb64(i64, -2, 1, .{ -4, false });
|
|
570
|
+
try test__shlo_limb64(i64, minInt(i64), 1, .{ 0, true });
|
|
571
|
+
try test__shlo_limb64(i64, minInt(i64), 63, .{ 0, true });
|
|
572
|
+
try test__shlo_limb64(i65, minInt(i63), 1, .{ minInt(i64), false });
|
|
573
|
+
try test__shlo_limb64(i65, -1, 17, .{ -1 << 17, false });
|
|
574
|
+
try test__shlo_limb64(i65, -3, 64, .{ -1 << 64, true });
|
|
575
|
+
try test__shlo_limb64(i128, -0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0, 4, .{ -0x2345_6789_ABCD_EF01_2345_6789_ABCD_EF00, true });
|
|
576
|
+
try test__shlo_limb64(i255, -3, 1, .{ -6, false });
|
|
577
|
+
try test__shlo_limb64(i633, 1 << 298, 333, .{ 1 << 631, false });
|
|
578
|
+
try test__shlo_limb64(i633, 1 << 299, 333, .{ minInt(i633), true });
|
|
579
|
+
try test__shlo_limb64(i633, 1 << 300, 333, .{ 0, true });
|
|
580
|
+
try test__shlo_limb64(i633, 1 << 297, 333, .{ 1 << 630, false });
|
|
581
|
+
try test__shlo_limb64(i633, -1 << 299, 333, .{ -1 << 632, false });
|
|
582
|
+
try test__shlo_limb64(i633, -1 << 300, 333, .{ 0, true });
|
|
583
|
+
try test__shlo_limb64(i633, -1 << 298, 333, .{ -1 << 631, false });
|
|
584
|
+
|
|
585
|
+
try test__shlo_limb64(u150, maxInt(u150), 1, .{ maxInt(u150) - 1, true });
|
|
586
|
+
try test__shlo_limb64(i150, -3, 1, .{ -6, false });
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
comptime {
|
|
590
|
+
symbol(&__shr_limb64, "__shr_limb64");
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) void {
|
|
594
|
+
const limb_cnt = usedLimbCount(bits);
|
|
595
|
+
const out = varLimbs(out_ptr, bits);
|
|
596
|
+
const a = constLimbs(a_ptr, bits);
|
|
597
|
+
|
|
598
|
+
assert(shift < bits);
|
|
599
|
+
|
|
600
|
+
const limb_shift = shift / 64;
|
|
601
|
+
const bit_shift = shift % 64;
|
|
602
|
+
|
|
603
|
+
const ms = limbGet(a, limb_cnt - 1);
|
|
604
|
+
const sign_extend: u64 = if (is_signed and (ms >> 63) == 1) ~@as(u64, 0) else 0;
|
|
605
|
+
|
|
606
|
+
var carry: u64 = if (bit_shift != 0) (sign_extend << @intCast(64 - bit_shift)) else 0;
|
|
607
|
+
var i: usize = 0;
|
|
608
|
+
while (i < limb_cnt) : (i += 1) {
|
|
609
|
+
const j = limb_cnt - 1 - i;
|
|
610
|
+
if (i < limb_shift) {
|
|
611
|
+
limbSet(out, j, sign_extend);
|
|
612
|
+
} else {
|
|
613
|
+
const limb = limbGet(a, j + limb_shift);
|
|
614
|
+
limbSet(out, j, (limb >> @intCast(bit_shift)) | carry);
|
|
615
|
+
carry = if (bit_shift != 0) (limb << @intCast(64 - bit_shift)) else 0;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
fn test__shr_limb64(comptime T: type, a: T, shift: u16, expected: T) !void {
|
|
623
|
+
const int_info = @typeInfo(T).int;
|
|
624
|
+
const is_signed = int_info.signedness == .signed;
|
|
625
|
+
|
|
626
|
+
var a_limbs = asLimbs(a);
|
|
627
|
+
var out: Limbs(T) = undefined;
|
|
628
|
+
__shr_limb64(&out, &a_limbs, shift, is_signed, int_info.bits);
|
|
629
|
+
|
|
630
|
+
const expected_limbs = asLimbs(expected);
|
|
631
|
+
try testing.expectEqual(expected_limbs, out);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
test __shr_limb64 {
|
|
635
|
+
try test__shr_limb64(u64, 0x1234_5678_9ABC_DEF0, 4, 0x0123_4567_89AB_CDEF);
|
|
636
|
+
try test__shr_limb64(u64, 0x8000_0000_0000_0001, 63, 1);
|
|
637
|
+
try test__shr_limb64(u65, 0x1_0000_0000_0000_0000, 64, 1);
|
|
638
|
+
try test__shr_limb64(u65, 0x1_0000_0000_0000_0001, 1, 0x0_8000_0000_0000_0000);
|
|
639
|
+
try test__shr_limb64(u128, 0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0, 4, 0x0123_4567_89AB_CDEF_0123_4567_89AB_CDEF);
|
|
640
|
+
try test__shr_limb64(u255, maxInt(u255), 1, maxInt(u254));
|
|
641
|
+
try test__shr_limb64(u633, 1 << 333, 333, 1);
|
|
642
|
+
try test__shr_limb64(u633, 1 << 334, 333, 2);
|
|
643
|
+
try test__shr_limb64(u633, 1 << 332, 333, 0);
|
|
644
|
+
|
|
645
|
+
try test__shr_limb64(i64, -2, 1, -1);
|
|
646
|
+
try test__shr_limb64(i64, minInt(i64), 63, -1);
|
|
647
|
+
try test__shr_limb64(i65, minInt(i65), 1, minInt(i65) | (1 << 63));
|
|
648
|
+
try test__shr_limb64(i65, -1, 17, -1);
|
|
649
|
+
try test__shr_limb64(i128, -0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0, 4, -0x0123_4567_89AB_CDEF_0123_4567_89AB_CDEF);
|
|
650
|
+
try test__shr_limb64(i255, -3, 1, -2);
|
|
651
|
+
try test__shr_limb64(i633, 1 << 333, 333, 1);
|
|
652
|
+
try test__shr_limb64(i633, 1 << 334, 333, 2);
|
|
653
|
+
try test__shr_limb64(i633, 1 << 332, 333, 0);
|
|
654
|
+
try test__shr_limb64(i633, -1 << 333, 333, -1);
|
|
655
|
+
try test__shr_limb64(i633, -1 << 334, 333, -2);
|
|
656
|
+
try test__shr_limb64(i633, -1 << 332, 333, -1);
|
|
657
|
+
|
|
658
|
+
try test__shr_limb64(u150, maxInt(u150), 1, maxInt(u149));
|
|
659
|
+
try test__shr_limb64(i150, -3, 1, -2);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
comptime {
|
|
663
|
+
symbol(&__clz_limb64, "__clz_limb64");
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
fn __clz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
|
|
667
|
+
const limb_cnt = usedLimbCount(bits);
|
|
668
|
+
const a = constLimbs(a_ptr, bits);
|
|
669
|
+
|
|
670
|
+
var res: u16 = 0;
|
|
671
|
+
var i: usize = 0;
|
|
672
|
+
|
|
673
|
+
if (bits % 64 != 0) {
|
|
674
|
+
const limb = limbGet(a, limb_cnt - 1);
|
|
675
|
+
if (limb == 0) {
|
|
676
|
+
res += bits % 64;
|
|
677
|
+
} else {
|
|
678
|
+
return @clz(limb << @intCast(64 - bits % 64));
|
|
679
|
+
}
|
|
680
|
+
i += 1;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
while (i < limb_cnt) : (i += 1) {
|
|
684
|
+
const j = limb_cnt - 1 - i;
|
|
685
|
+
const limb = limbGet(a, j);
|
|
686
|
+
if (limb == 0) {
|
|
687
|
+
res += 64;
|
|
688
|
+
} else {
|
|
689
|
+
res += @clz(limb);
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return res;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
fn test__clz_limb64(comptime T: type, a: T, expected: u16) !void {
|
|
698
|
+
const int_info = @typeInfo(T).int;
|
|
699
|
+
|
|
700
|
+
var a_limbs = asLimbs(a);
|
|
701
|
+
const out = __clz_limb64(&a_limbs, int_info.bits);
|
|
702
|
+
|
|
703
|
+
try testing.expectEqual(expected, out);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
test __clz_limb64 {
|
|
707
|
+
try test__clz_limb64(u64, 0, 64);
|
|
708
|
+
try test__clz_limb64(u65, 1 << 64, 0);
|
|
709
|
+
try test__clz_limb64(u65, 1 << 9, 55);
|
|
710
|
+
try test__clz_limb64(u128, 1 << 31, 96);
|
|
711
|
+
try test__clz_limb64(u255, 1 << 62, 192);
|
|
712
|
+
|
|
713
|
+
try test__clz_limb64(i64, -1, 0);
|
|
714
|
+
try test__clz_limb64(i65, minInt(i65), 0);
|
|
715
|
+
try test__clz_limb64(i65, 1 << 32, 32);
|
|
716
|
+
try test__clz_limb64(i128, 0, 128);
|
|
717
|
+
try test__clz_limb64(i255, 1 << 130, 124);
|
|
718
|
+
|
|
719
|
+
try test__clz_limb64(u150, 1 << 31, 118);
|
|
720
|
+
try test__clz_limb64(i150, maxInt(u65) - 1, 85);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
comptime {
|
|
724
|
+
symbol(&__ctz_limb64, "__ctz_limb64");
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
fn __ctz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
|
|
728
|
+
const limb_cnt = usedLimbCount(bits);
|
|
729
|
+
const a = constLimbs(a_ptr, bits);
|
|
730
|
+
|
|
731
|
+
var res: u16 = 0;
|
|
732
|
+
var i: usize = 0;
|
|
733
|
+
while (i < limb_cnt - 1) : (i += 1) {
|
|
734
|
+
const limb = limbGet(a, i);
|
|
735
|
+
if (limb == 0) {
|
|
736
|
+
res += 64;
|
|
737
|
+
} else {
|
|
738
|
+
res += @ctz(limb);
|
|
739
|
+
return res;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const limb = limbGet(a, i);
|
|
744
|
+
if (bits % 64 != 0 and limb == 0) {
|
|
745
|
+
res += bits % 64;
|
|
746
|
+
} else {
|
|
747
|
+
res += @ctz(limb);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
return res;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
fn test__ctz_limb64(comptime T: type, a: T, expected: u16) !void {
|
|
754
|
+
const int_info = @typeInfo(T).int;
|
|
755
|
+
|
|
756
|
+
var a_limbs = asLimbs(a);
|
|
757
|
+
const out = __ctz_limb64(&a_limbs, int_info.bits);
|
|
758
|
+
|
|
759
|
+
try testing.expectEqual(expected, out);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
test __ctz_limb64 {
|
|
763
|
+
try test__ctz_limb64(u64, 1 << 17, 17);
|
|
764
|
+
try test__ctz_limb64(u65, 1 << 64, 64);
|
|
765
|
+
try test__ctz_limb64(u65, 0, 65);
|
|
766
|
+
try test__ctz_limb64(u128, 1 << 100, 100);
|
|
767
|
+
try test__ctz_limb64(u255, 1 << 200, 200);
|
|
768
|
+
|
|
769
|
+
try test__ctz_limb64(i64, -1 << 9, 9);
|
|
770
|
+
try test__ctz_limb64(i65, minInt(i65), 64);
|
|
771
|
+
try test__ctz_limb64(i65, 0, 65);
|
|
772
|
+
try test__ctz_limb64(i128, -1 << 73, 73);
|
|
773
|
+
try test__ctz_limb64(i255, 1 << 130, 130);
|
|
774
|
+
|
|
775
|
+
try test__ctz_limb64(u150, 1 << 101, 101);
|
|
776
|
+
try test__ctz_limb64(i150, -1 << 74, 74);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
comptime {
|
|
780
|
+
symbol(&__popcount_limb64, "__popcount_limb64");
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
fn __popcount_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
|
|
784
|
+
const limb_cnt = usedLimbCount(bits);
|
|
785
|
+
const a = constLimbs(a_ptr, bits);
|
|
786
|
+
|
|
787
|
+
var res: u16 = 0;
|
|
788
|
+
var i: usize = 0;
|
|
789
|
+
while (i < limb_cnt - 1) : (i += 1) {
|
|
790
|
+
res += @popCount(limbGet(a, i));
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
var limb = limbGet(a, i);
|
|
794
|
+
if (bits % 64 != 0) {
|
|
795
|
+
limb <<= @intCast(64 - bits % 64);
|
|
796
|
+
}
|
|
797
|
+
res += @popCount(limb);
|
|
798
|
+
|
|
799
|
+
return res;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
fn test__popcount_limb64(comptime T: type, a: T, expected: u16) !void {
|
|
803
|
+
const int_info = @typeInfo(T).int;
|
|
804
|
+
|
|
805
|
+
var a_limbs = asLimbs(a);
|
|
806
|
+
const out = __popcount_limb64(&a_limbs, int_info.bits);
|
|
807
|
+
|
|
808
|
+
try testing.expectEqual(expected, out);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
test __popcount_limb64 {
|
|
812
|
+
try test__popcount_limb64(u64, 0xF0F0_0000_0000_0001, 9);
|
|
813
|
+
try test__popcount_limb64(u65, 1 << 64, 1);
|
|
814
|
+
try test__popcount_limb64(u65, maxInt(u65), 65);
|
|
815
|
+
try test__popcount_limb64(u128, (1 << 100) | (1 << 5) | 1, 3);
|
|
816
|
+
try test__popcount_limb64(u255, maxInt(u255), 255);
|
|
817
|
+
|
|
818
|
+
try test__popcount_limb64(i64, -1, 64);
|
|
819
|
+
try test__popcount_limb64(i65, minInt(i65), 1);
|
|
820
|
+
try test__popcount_limb64(i65, -1, 65);
|
|
821
|
+
try test__popcount_limb64(i128, -1 << 7, 121);
|
|
822
|
+
try test__popcount_limb64(i255, -1 << 200, 55);
|
|
823
|
+
|
|
824
|
+
try test__popcount_limb64(u150, (1 << 149) | (1 << 65) | 1, 3);
|
|
825
|
+
try test__popcount_limb64(i150, -1 << 7, 143);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
comptime {
|
|
829
|
+
symbol(&__bitreverse_limb64, "__bitreverse_limb64");
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
fn __bitreverse_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
|
|
833
|
+
const limb_cnt = usedLimbCount(bits);
|
|
834
|
+
const out = varLimbs(out_ptr, bits);
|
|
835
|
+
const a = constLimbs(a_ptr, bits);
|
|
836
|
+
|
|
837
|
+
var i: usize = 0;
|
|
838
|
+
while (i < limb_cnt) : (i += 1) {
|
|
839
|
+
const j = limb_cnt - 1 - i;
|
|
840
|
+
limbSet(out, j, @bitReverse(limbGet(a, i)));
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (bits % 64 != 0) {
|
|
844
|
+
__shr_limb64(out_ptr, out_ptr, 64 - bits % 64, is_signed, bits);
|
|
845
|
+
}
|
|
846
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
fn test__bitreverse_limb64(comptime T: type, a: T, expected: T) !void {
|
|
850
|
+
const int_info = @typeInfo(T).int;
|
|
851
|
+
const is_signed = int_info.signedness == .signed;
|
|
852
|
+
|
|
853
|
+
var a_limbs = asLimbs(a);
|
|
854
|
+
var out: Limbs(T) = undefined;
|
|
855
|
+
__bitreverse_limb64(&out, &a_limbs, is_signed, int_info.bits);
|
|
856
|
+
|
|
857
|
+
const expected_limbs = asLimbs(expected);
|
|
858
|
+
try testing.expectEqual(expected_limbs, out);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
test __bitreverse_limb64 {
|
|
862
|
+
try test__bitreverse_limb64(u64, 1 << 7, 1 << 56);
|
|
863
|
+
try test__bitreverse_limb64(u65, 1 << 64, 1);
|
|
864
|
+
try test__bitreverse_limb64(u65, 1 << 9, 1 << 55);
|
|
865
|
+
try test__bitreverse_limb64(u128, 1 << 100, 1 << 27);
|
|
866
|
+
try test__bitreverse_limb64(u255, 1 << 200, 1 << 54);
|
|
867
|
+
|
|
868
|
+
try test__bitreverse_limb64(i64, -1, -1);
|
|
869
|
+
try test__bitreverse_limb64(i65, 1 << 32, 1 << 32);
|
|
870
|
+
try test__bitreverse_limb64(i65, minInt(i65), 1);
|
|
871
|
+
try test__bitreverse_limb64(i128, 1 << 63, 1 << 64);
|
|
872
|
+
try test__bitreverse_limb64(i255, 1 << 130, 1 << 124);
|
|
873
|
+
|
|
874
|
+
try test__bitreverse_limb64(u150, 1 << 9, 1 << 140);
|
|
875
|
+
try test__bitreverse_limb64(i150, minInt(i150), 1);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
comptime {
|
|
879
|
+
symbol(&__byteswap_limb64, "__byteswap_limb64");
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
fn __byteswap_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
|
|
883
|
+
const limb_cnt = usedLimbCount(bits);
|
|
884
|
+
const out = varLimbs(out_ptr, bits);
|
|
885
|
+
const a = constLimbs(a_ptr, bits);
|
|
886
|
+
|
|
887
|
+
assert(bits % 8 == 0);
|
|
888
|
+
|
|
889
|
+
var i: usize = 0;
|
|
890
|
+
while (i < limb_cnt) : (i += 1) {
|
|
891
|
+
const j = limb_cnt - 1 - i;
|
|
892
|
+
limbSet(out, j, @byteSwap(limbGet(a, i)));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (bits % 64 != 0) {
|
|
896
|
+
__shr_limb64(out_ptr, out_ptr, 64 - bits % 64, is_signed, bits);
|
|
897
|
+
}
|
|
898
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
fn test__byteswap_limb64(comptime T: type, a: T, expected: T) !void {
|
|
902
|
+
const int_info = @typeInfo(T).int;
|
|
903
|
+
const is_signed = int_info.signedness == .signed;
|
|
904
|
+
|
|
905
|
+
var a_limbs = asLimbs(a);
|
|
906
|
+
var out: Limbs(T) = undefined;
|
|
907
|
+
__byteswap_limb64(&out, &a_limbs, is_signed, int_info.bits);
|
|
908
|
+
|
|
909
|
+
const expected_limbs = asLimbs(expected);
|
|
910
|
+
try testing.expectEqual(expected_limbs, out);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
test __byteswap_limb64 {
|
|
914
|
+
try test__byteswap_limb64(u64, 0x0123_4567_89AB_CDEF, 0xEFCD_AB89_6745_2301);
|
|
915
|
+
try test__byteswap_limb64(u72, 0x01_23_45_67_89_AB_CD_EF_11, 0x11_EF_CD_AB_89_67_45_23_01);
|
|
916
|
+
try test__byteswap_limb64(u128, 1 << 72, 1 << 48);
|
|
917
|
+
try test__byteswap_limb64(u248, 1, 1 << 240);
|
|
918
|
+
try test__byteswap_limb64(u256, 1 << 120, 1 << 128);
|
|
919
|
+
|
|
920
|
+
try test__byteswap_limb64(i64, minInt(i64), 128);
|
|
921
|
+
try test__byteswap_limb64(i72, 1, 1 << 64);
|
|
922
|
+
try test__byteswap_limb64(i72, -1, -1);
|
|
923
|
+
try test__byteswap_limb64(i128, 1 << 56, 1 << 64);
|
|
924
|
+
try test__byteswap_limb64(i248, minInt(i248), 128);
|
|
925
|
+
|
|
926
|
+
try test__byteswap_limb64(u152, 1, 1 << 144);
|
|
927
|
+
try test__byteswap_limb64(i152, 1 << 56, 1 << 88);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
comptime {
|
|
931
|
+
symbol(&__mulo_limb64, "__mulo_limb64");
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
inline fn add3(x: *[3]u64, start: usize, v0: u64) void {
|
|
935
|
+
var i = start;
|
|
936
|
+
var v = v0;
|
|
937
|
+
while (i < 3) : (i += 1) {
|
|
938
|
+
const s = @addWithOverflow(x[i], v);
|
|
939
|
+
x[i] = s[0];
|
|
940
|
+
if (s[1] == 0) break;
|
|
941
|
+
v = 1;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
fn mulwide(a: u64, b: u64) [2]u64 {
|
|
946
|
+
const muldXi = @import("mulXi3.zig").muldXi;
|
|
947
|
+
const limbs: [2]u64 = @bitCast(muldXi(u64, a, b));
|
|
948
|
+
return switch (endian) {
|
|
949
|
+
.little => limbs,
|
|
950
|
+
.big => .{ limbs[1], limbs[0] },
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
|
|
955
|
+
const limb_cnt = usedLimbCount(bits);
|
|
956
|
+
|
|
957
|
+
const out = varLimbs(out_ptr, bits);
|
|
958
|
+
const a = constLimbs(a_ptr, bits);
|
|
959
|
+
const b = constLimbs(b_ptr, bits);
|
|
960
|
+
|
|
961
|
+
@memset(out, 0);
|
|
962
|
+
|
|
963
|
+
const all_ones = ~@as(u64, 0);
|
|
964
|
+
const a_neg = is_signed and ((limbGet(a, limb_cnt - 1) >> 63) != 0);
|
|
965
|
+
const b_neg = is_signed and ((limbGet(b, limb_cnt - 1) >> 63) != 0);
|
|
966
|
+
|
|
967
|
+
var carry: [3]u64 = @splat(0);
|
|
968
|
+
var hi_zero = true;
|
|
969
|
+
var hi_ones = true;
|
|
970
|
+
var hi_borrow: u1 = 0;
|
|
971
|
+
var raw_last: u64 = 0;
|
|
972
|
+
|
|
973
|
+
var k: usize = 0;
|
|
974
|
+
while (k < 2 * limb_cnt) : (k += 1) {
|
|
975
|
+
var acc = carry;
|
|
976
|
+
|
|
977
|
+
var i: usize = if (k < limb_cnt) 0 else k - (limb_cnt - 1);
|
|
978
|
+
while (i < limb_cnt and i <= k) : (i += 1) {
|
|
979
|
+
const j = k - i;
|
|
980
|
+
if (j >= limb_cnt) continue;
|
|
981
|
+
|
|
982
|
+
const p = mulwide(limbGet(a, i), limbGet(b, j));
|
|
983
|
+
add3(&acc, 0, p[0]);
|
|
984
|
+
add3(&acc, 1, p[1]);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
var limb = acc[0];
|
|
988
|
+
if (k < limb_cnt) {
|
|
989
|
+
limbSet(out, k, limb);
|
|
990
|
+
if (k == limb_cnt - 1) raw_last = limb;
|
|
991
|
+
} else {
|
|
992
|
+
if (is_signed) {
|
|
993
|
+
const h = k - limb_cnt;
|
|
994
|
+
|
|
995
|
+
const s0 = @subWithOverflow(limb, if (a_neg) limbGet(b, h) else 0);
|
|
996
|
+
const s1 = @subWithOverflow(s0[0], if (b_neg) limbGet(a, h) else 0);
|
|
997
|
+
const s2 = @subWithOverflow(s1[0], hi_borrow);
|
|
998
|
+
|
|
999
|
+
limb = s2[0];
|
|
1000
|
+
hi_borrow = @intFromBool(s0[1] != 0 or s1[1] != 0 or s2[1] != 0);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
hi_zero = hi_zero and limb == 0;
|
|
1004
|
+
hi_ones = hi_ones and limb == all_ones;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
carry = .{ acc[1], acc[2], 0 };
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const last = if (bits % 64 == 0) raw_last else limbWrap(raw_last, is_signed, bits);
|
|
1011
|
+
if (bits % 64 != 0) {
|
|
1012
|
+
limbSet(out, limb_cnt - 1, last);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
fixLastLimb(out_ptr, is_signed, bits);
|
|
1016
|
+
|
|
1017
|
+
if (!is_signed) {
|
|
1018
|
+
return !hi_zero or raw_last != last;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
const sign_extend: u64 = if ((last >> 63) == 1) all_ones else 0;
|
|
1022
|
+
return (raw_last != last) or if (sign_extend == 0) !hi_zero else !hi_ones;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
fn test__mulo_limb64(comptime T: type, a: T, b: T, expected: struct { T, bool }) !void {
|
|
1026
|
+
const int_info = @typeInfo(T).int;
|
|
1027
|
+
const is_signed = int_info.signedness == .signed;
|
|
1028
|
+
|
|
1029
|
+
var a_limbs = asLimbs(a);
|
|
1030
|
+
var b_limbs = asLimbs(b);
|
|
1031
|
+
var out: Limbs(T) = undefined;
|
|
1032
|
+
const overflow = __mulo_limb64(&out, &a_limbs, &b_limbs, is_signed, int_info.bits);
|
|
1033
|
+
|
|
1034
|
+
const expected_limbs = asLimbs(expected[0]);
|
|
1035
|
+
try testing.expectEqual(expected_limbs, out);
|
|
1036
|
+
try testing.expectEqual(expected[1], overflow);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
test __mulo_limb64 {
|
|
1040
|
+
try test__mulo_limb64(u64, 3, 5, .{ 15, false });
|
|
1041
|
+
try test__mulo_limb64(u64, maxInt(u64), 2, .{ maxInt(u64) - 1, true });
|
|
1042
|
+
try test__mulo_limb64(u65, 1 << 32, 1 << 32, .{ 1 << 64, false });
|
|
1043
|
+
try test__mulo_limb64(u65, 1 << 64, 2, .{ 0, true });
|
|
1044
|
+
try test__mulo_limb64(u128, 1 << 80, 1 << 40, .{ 1 << 120, false });
|
|
1045
|
+
try test__mulo_limb64(u128, 1 << 100, 1 << 40, .{ 0, true });
|
|
1046
|
+
try test__mulo_limb64(u255, 7, 9, .{ 63, false });
|
|
1047
|
+
try test__mulo_limb64(u255, maxInt(u255), 2, .{ maxInt(u255) - 1, true });
|
|
1048
|
+
|
|
1049
|
+
try test__mulo_limb64(i64, -3, 2, .{ -6, false });
|
|
1050
|
+
try test__mulo_limb64(i64, maxInt(i64), 2, .{ -2, true });
|
|
1051
|
+
try test__mulo_limb64(i65, 1 << 63, 2, .{ minInt(i65), true });
|
|
1052
|
+
try test__mulo_limb64(i65, -1 << 32, 1 << 16, .{ -1 << 48, false });
|
|
1053
|
+
try test__mulo_limb64(i128, 1 << 100, 1 << 27, .{ minInt(i128), true });
|
|
1054
|
+
try test__mulo_limb64(i128, -1 << 80, 1 << 40, .{ -1 << 120, false });
|
|
1055
|
+
try test__mulo_limb64(i255, -3, 2, .{ -6, false });
|
|
1056
|
+
try test__mulo_limb64(i255, maxInt(i255), 2, .{ -2, true });
|
|
1057
|
+
|
|
1058
|
+
try test__mulo_limb64(u200, 0, maxInt(u200), .{ 0, false });
|
|
1059
|
+
try test__mulo_limb64(u200, 1, maxInt(u200), .{ maxInt(u200), false });
|
|
1060
|
+
try test__mulo_limb64(u200, 1 << 100, 1 << 99, .{ 1 << 199, false });
|
|
1061
|
+
try test__mulo_limb64(u200, 1 << 100, 1 << 100, .{ 0, true });
|
|
1062
|
+
try test__mulo_limb64(u200, maxInt(u200), maxInt(u200), .{ 1, true });
|
|
1063
|
+
|
|
1064
|
+
try test__mulo_limb64(i200, 0, -1, .{ 0, false });
|
|
1065
|
+
try test__mulo_limb64(i200, -1, -1, .{ 1, false });
|
|
1066
|
+
try test__mulo_limb64(i200, -1, minInt(i200), .{ minInt(i200), true });
|
|
1067
|
+
try test__mulo_limb64(i200, maxInt(i200), 2, .{ -2, true });
|
|
1068
|
+
try test__mulo_limb64(i200, 1 << 100, 1 << 98, .{ 1 << 198, false });
|
|
1069
|
+
try test__mulo_limb64(i200, 1 << 100, 1 << 99, .{ minInt(i200), true });
|
|
1070
|
+
try test__mulo_limb64(i200, maxInt(i200), maxInt(i200), .{ 1, true });
|
|
1071
|
+
try test__mulo_limb64(i200, minInt(i200), minInt(i200), .{ 0, true });
|
|
1072
|
+
|
|
1073
|
+
try test__mulo_limb64(u150, maxInt(u150), 2, .{ maxInt(u150) - 1, true });
|
|
1074
|
+
try test__mulo_limb64(i150, maxInt(i150), 2, .{ -2, true });
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
comptime {
|
|
1078
|
+
symbol(&__abs_limb64, "__abs_limb64");
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
fn __abs_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, bits: u16) callconv(.c) void {
|
|
1082
|
+
const limb_cnt = limbCount(bits);
|
|
1083
|
+
const out = out_ptr[0..limb_cnt];
|
|
1084
|
+
const a = a_ptr[0..limb_cnt];
|
|
1085
|
+
|
|
1086
|
+
const ms = limbGet(a, limb_cnt - 1);
|
|
1087
|
+
if ((ms >> 63) == 0) {
|
|
1088
|
+
@memcpy(out, a);
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
var carry: u1 = 1;
|
|
1093
|
+
var i: usize = 0;
|
|
1094
|
+
while (i < limb_cnt) : (i += 1) {
|
|
1095
|
+
const s = @addWithOverflow(~limbGet(a, i), carry);
|
|
1096
|
+
limbSet(out, i, s[0]);
|
|
1097
|
+
carry = s[1];
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
fn test__abs_limb64(comptime T: type, a: T, expected: @Int(.unsigned, @typeInfo(T).int.bits)) !void {
|
|
1102
|
+
const int_info = @typeInfo(T).int;
|
|
1103
|
+
comptime assert(int_info.signedness == .signed);
|
|
1104
|
+
|
|
1105
|
+
var a_limbs = asLimbs(a);
|
|
1106
|
+
var out: Limbs(@TypeOf(expected)) = undefined;
|
|
1107
|
+
__abs_limb64(&out, &a_limbs, int_info.bits);
|
|
1108
|
+
|
|
1109
|
+
const expected_limbs = asLimbs(expected);
|
|
1110
|
+
try testing.expectEqual(expected_limbs, out);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
test __abs_limb64 {
|
|
1114
|
+
try test__abs_limb64(i64, 0, 0);
|
|
1115
|
+
try test__abs_limb64(i64, -1, 1);
|
|
1116
|
+
try test__abs_limb64(i64, minInt(i64), 1 << 63);
|
|
1117
|
+
try test__abs_limb64(i65, -1, 1);
|
|
1118
|
+
try test__abs_limb64(i65, minInt(i65), 1 << 64);
|
|
1119
|
+
try test__abs_limb64(i65, maxInt(i65), maxInt(i65));
|
|
1120
|
+
try test__abs_limb64(i128, -1 << 80, 1 << 80);
|
|
1121
|
+
try test__abs_limb64(i128, 1 << 64, 1 << 64);
|
|
1122
|
+
try test__abs_limb64(i200, -1 << 198, 1 << 198);
|
|
1123
|
+
try test__abs_limb64(i255, -5, 5);
|
|
1124
|
+
try test__abs_limb64(i255, minInt(i255), 1 << 254);
|
|
1125
|
+
|
|
1126
|
+
try test__abs_limb64(i150, -40, 40);
|
|
266
1127
|
}
|