diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-03-05 14:48:06 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-05 14:48:06 -0500 |
| commit | 7b01af2bfd4cf9232fb0157c26d7c59642452fab (patch) | |
| tree | 733810a59ad5a4177198d60b9058e2951567a94a /lib | |
| parent | a63134a4a56e8683aeee292b641b4e943cbfb999 (diff) | |
| parent | 1efd36cd5c9a1128ae702b081d60ee32f21bc258 (diff) | |
| download | zig-7b01af2bfd4cf9232fb0157c26d7c59642452fab.tar.gz zig-7b01af2bfd4cf9232fb0157c26d7c59642452fab.zip | |
Merge pull request #14745 from jacobly0/bigint
CBE: add support for integers larger than 128 bits (and apparently vectors too)
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/math/big/int.zig | 1 | ||||
| -rw-r--r-- | lib/zig.h | 1247 |
2 files changed, 1036 insertions, 212 deletions
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index b7725b9ae9..4e4e7c489e 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -1674,6 +1674,7 @@ pub const Mutable = struct { /// If a is positive, this passes through to truncate. /// If a is negative, then r is set to positive with the bit pattern ~(a - 1). + /// r may alias a. /// /// Asserts `r` has enough storage to store the result. /// The upper bound is `calcTwosCompLimbCount(a.len)`. @@ -37,6 +37,14 @@ typedef char bool; #define zig_has_attribute(attribute) 0 #endif +#if __LITTLE_ENDIAN__ || _MSC_VER +#define zig_little_endian 1 +#define zig_big_endian 0 +#else +#define zig_little_endian 0 +#define zig_big_endian 1 +#endif + #if __STDC_VERSION__ >= 201112L #define zig_threadlocal _Thread_local #elif defined(__GNUC__) @@ -604,12 +612,6 @@ static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -static inline void zig_vaddo_u32(uint8_t *ov, uint32_t *res, int n, - const uint32_t *lhs, const uint32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) @@ -624,12 +626,6 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } -static inline void zig_vaddo_i32(uint8_t *ov, int32_t *res, int n, - const int32_t *lhs, const int32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) uint64_t full_res; @@ -642,12 +638,6 @@ static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -static inline void zig_vaddo_u64(uint8_t *ov, uint64_t *res, int n, - const uint64_t *lhs, const uint64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) @@ -662,12 +652,6 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } -static inline void zig_vaddo_i64(uint8_t *ov, int64_t *res, int n, - const int64_t *lhs, const int64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) uint8_t full_res; @@ -682,12 +666,6 @@ static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #endif } -static inline void zig_vaddo_u8(uint8_t *ov, uint8_t *res, int n, - const uint8_t *lhs, const uint8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) int8_t full_res; @@ -702,12 +680,6 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #endif } -static inline void zig_vaddo_i8(uint8_t *ov, int8_t *res, int n, - const int8_t *lhs, const int8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) uint16_t full_res; @@ -722,12 +694,6 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #endif } -static inline void zig_vaddo_u16(uint8_t *ov, uint16_t *res, int n, - const uint16_t *lhs, const uint16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gnuc) int16_t full_res; @@ -742,12 +708,6 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } -static inline void zig_vaddo_i16(uint8_t *ov, int16_t *res, int n, - const int16_t *lhs, const int16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) uint32_t full_res; @@ -760,12 +720,6 @@ static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -static inline void zig_vsubo_u32(uint8_t *ov, uint32_t *res, int n, - const uint32_t *lhs, const uint32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) @@ -780,12 +734,6 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } -static inline void zig_vsubo_i32(uint8_t *ov, int32_t *res, int n, - const int32_t *lhs, const int32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) uint64_t full_res; @@ -798,12 +746,6 @@ static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -static inline void zig_vsubo_u64(uint8_t *ov, uint64_t *res, int n, - const uint64_t *lhs, const uint64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) @@ -818,12 +760,6 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } -static inline void zig_vsubo_i64(uint8_t *ov, int64_t *res, int n, - const int64_t *lhs, const int64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) uint8_t full_res; @@ -838,12 +774,6 @@ static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #endif } -static inline void zig_vsubo_u8(uint8_t *ov, uint8_t *res, int n, - const uint8_t *lhs, const uint8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) int8_t full_res; @@ -858,13 +788,6 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #endif } -static inline void zig_vsubo_i8(uint8_t *ov, int8_t *res, int n, - const int8_t *lhs, const int8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits); -} - - static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) uint16_t full_res; @@ -879,13 +802,6 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #endif } -static inline void zig_vsubo_u16(uint8_t *ov, uint16_t *res, int n, - const uint16_t *lhs, const uint16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits); -} - - static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gnuc) int16_t full_res; @@ -900,12 +816,6 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } -static inline void zig_vsubo_i16(uint8_t *ov, int16_t *res, int n, - const int16_t *lhs, const int16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) uint32_t full_res; @@ -918,12 +828,6 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -static inline void zig_vmulo_u32(uint8_t *ov, uint32_t *res, int n, - const uint32_t *lhs, const uint32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) @@ -938,12 +842,6 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } -static inline void zig_vmulo_i32(uint8_t *ov, int32_t *res, int n, - const int32_t *lhs, const int32_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) uint64_t full_res; @@ -956,12 +854,6 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -static inline void zig_vmulo_u64(uint8_t *ov, uint64_t *res, int n, - const uint64_t *lhs, const uint64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits); -} - zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) @@ -976,12 +868,6 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } -static inline void zig_vmulo_i64(uint8_t *ov, int64_t *res, int n, - const int64_t *lhs, const int64_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) uint8_t full_res; @@ -996,12 +882,6 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #endif } -static inline void zig_vmulo_u8(uint8_t *ov, uint8_t *res, int n, - const uint8_t *lhs, const uint8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) int8_t full_res; @@ -1016,12 +896,6 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #endif } -static inline void zig_vmulo_i8(uint8_t *ov, int8_t *res, int n, - const int8_t *lhs, const int8_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) uint16_t full_res; @@ -1036,12 +910,6 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #endif } -static inline void zig_vmulo_u16(uint8_t *ov, uint16_t *res, int n, - const uint16_t *lhs, const uint16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits); -} - static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gnuc) int16_t full_res; @@ -1056,12 +924,6 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } -static inline void zig_vmulo_i16(uint8_t *ov, int16_t *res, int n, - const int16_t *lhs, const int16_t *rhs, uint8_t bits) -{ - for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits); -} - #define zig_int_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ @@ -1360,8 +1222,8 @@ typedef signed __int128 zig_i128; #define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) #define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo) +#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) +#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) #define zig_hi_u128(val) ((uint64_t)((val) >> 64)) #define zig_lo_u128(val) ((uint64_t)((val) >> 0)) #define zig_hi_i128(val) (( int64_t)((val) >> 64)) @@ -1379,7 +1241,7 @@ typedef signed __int128 zig_i128; #else /* zig_has_int128 */ -#if __LITTLE_ENDIAN__ || _MSC_VER +#if zig_little_endian typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; #else @@ -1391,11 +1253,11 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; #define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) #if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } +#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } +#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } #else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo) +#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) +#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) #endif #define zig_hi_u128(val) ((val).hi) #define zig_lo_u128(val) ((val).lo) @@ -1638,7 +1500,9 @@ static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { } static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); + if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); + int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); } static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { @@ -1909,6 +1773,972 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits)); } +/* ========================== Big Integer Support =========================== */ + +static inline uint16_t zig_int_bytes(uint16_t bits) { + uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; + return (bytes + alignment - 1) / alignment * alignment; +} + +static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int8_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + +static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t top_bits = remaining_bytes * 8 - bits; + bool overflow = false; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes == 128 / CHAR_BIT && is_signed) { + zig_i128 res_limb; + zig_i128 tmp_limb; + zig_i128 lhs_limb; + zig_i128 rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 tmp_limb; + zig_u128 lhs_limb; + zig_u128 rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes == 64 / CHAR_BIT && is_signed) { + int64_t res_limb; + int64_t tmp_limb; + int64_t lhs_limb; + int64_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t tmp_limb; + uint64_t lhs_limb; + uint64_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes == 32 / CHAR_BIT && is_signed) { + int32_t res_limb; + int32_t tmp_limb; + int32_t lhs_limb; + int32_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t tmp_limb; + uint32_t lhs_limb; + uint32_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes == 16 / CHAR_BIT && is_signed) { + int16_t res_limb; + int16_t tmp_limb; + int16_t lhs_limb; + int16_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t tmp_limb; + uint16_t lhs_limb; + uint16_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes == 8 / CHAR_BIT && is_signed) { + int8_t res_limb; + int8_t tmp_limb; + int8_t lhs_limb; + int8_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t tmp_limb; + uint8_t lhs_limb; + uint8_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_addo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_addo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return overflow; +} + +static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t top_bits = remaining_bytes * 8 - bits; + bool overflow = false; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes == 128 / CHAR_BIT && is_signed) { + zig_i128 res_limb; + zig_i128 tmp_limb; + zig_i128 lhs_limb; + zig_i128 rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 tmp_limb; + zig_u128 lhs_limb; + zig_u128 rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes == 64 / CHAR_BIT && is_signed) { + int64_t res_limb; + int64_t tmp_limb; + int64_t lhs_limb; + int64_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t tmp_limb; + uint64_t lhs_limb; + uint64_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes == 32 / CHAR_BIT && is_signed) { + int32_t res_limb; + int32_t tmp_limb; + int32_t lhs_limb; + int32_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t tmp_limb; + uint32_t lhs_limb; + uint32_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes == 16 / CHAR_BIT && is_signed) { + int16_t res_limb; + int16_t tmp_limb; + int16_t lhs_limb; + int16_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t tmp_limb; + uint16_t lhs_limb; + uint16_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes == 8 / CHAR_BIT && is_signed) { + int8_t res_limb; + int8_t tmp_limb; + int8_t lhs_limb; + int8_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t tmp_limb; + uint8_t lhs_limb; + uint8_t rhs_limb; + bool limb_overflow; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); + limb_overflow = zig_subo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits); + overflow = limb_overflow ^ zig_subo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return overflow; +} + +static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_addo_big(res, lhs, rhs, is_signed, bits); +} + +static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_subo_big(res, lhs, rhs, is_signed, bits); +} + +static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { + const uint8_t *val_bytes = val; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t skip_bits = remaining_bytes * 8 - bits; + uint16_t total_lz = 0; + uint16_t limb_lz; + (void)is_signed; + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + } + + total_lz += limb_lz; + if (limb_lz < 128 - skip_bits) return total_lz; + skip_bits = 0; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + } + + total_lz += limb_lz; + if (limb_lz < 64 - skip_bits) return total_lz; + skip_bits = 0; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); + } + + total_lz += limb_lz; + if (limb_lz < 32 - skip_bits) return total_lz; + skip_bits = 0; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + } + + total_lz += limb_lz; + if (limb_lz < 16 - skip_bits) return total_lz; + skip_bits = 0; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + } + + total_lz += limb_lz; + if (limb_lz < 8 - skip_bits) return total_lz; + skip_bits = 0; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + +static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { + const uint8_t *val_bytes = val; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t total_tz = 0; + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_tz = zig_ctz_u128(val_limb, 128); + } + + total_tz += limb_tz; + if (limb_tz < 128) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_tz = zig_ctz_u64(val_limb, 64); + } + + total_tz += limb_tz; + if (limb_tz < 64) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_tz = zig_ctz_u32(val_limb, 32); + } + + total_tz += limb_tz; + if (limb_tz < 32) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_tz = zig_ctz_u16(val_limb, 16); + } + + total_tz += limb_tz; + if (limb_tz < 16) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + limb_tz = zig_ctz_u8(val_limb, 8); + } + + total_tz += limb_tz; + if (limb_tz < 8) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { + const uint8_t *val_bytes = val; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t total_pc = 0; + (void)is_signed; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + total_pc += zig_popcount_u128(val_limb, 128); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + total_pc += zig_popcount_u64(val_limb, 64); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + total_pc += zig_popcount_u32(val_limb, 32); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + total_pc = zig_popcount_u16(val_limb, 16); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t val_limb; + + memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); + total_pc = zig_popcount_u8(val_limb, 8); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_pc; +} + /* ========================= Floating Point Support ========================= */ #if _MSC_VER @@ -1933,7 +2763,6 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { #define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64(__builtin_##name, )(arg) #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80(__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) -#define zig_make_special_c_longdouble(sign, name, arg, repr) sign zig_make_c_longdouble(__builtin_##name, )(arg) #else #define zig_has_float_builtins 0 #define zig_make_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr) @@ -1941,13 +2770,13 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { #define zig_make_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr) #define zig_make_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr) #define zig_make_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr) -#define zig_make_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr) #endif #define zig_has_f16 1 #define zig_bitSizeOf_f16 16 +typedef int16_t zig_repr_f16; #define zig_libc_name_f16(name) __##name##h -#define zig_make_special_constant_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) +#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) #if FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f @@ -1956,7 +2785,9 @@ typedef double zig_f16; #define zig_make_f16(fp, repr) fp #elif LDBL_MANT_DIG == 11 #define zig_bitSizeOf_c_longdouble 16 -typedef uint16_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f16 zig_repr_c_longdouble; +#endif typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l #elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc)) @@ -1973,17 +2804,18 @@ typedef int16_t zig_f16; #define zig_make_f16(fp, repr) repr #undef zig_make_special_f16 #define zig_make_special_f16(sign, name, arg, repr) repr -#undef zig_make_special_constant_f16 -#define zig_make_special_constant_f16(sign, name, arg, repr) repr +#undef zig_init_special_f16 +#define zig_init_special_f16(sign, name, arg, repr) repr #endif #define zig_has_f32 1 #define zig_bitSizeOf_f32 32 +typedef int32_t zig_repr_f32; #define zig_libc_name_f32(name) name##f #if _MSC_VER -#define zig_make_special_constant_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, ) +#define zig_init_special_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, ) #else -#define zig_make_special_constant_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) +#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif #if FLT_MANT_DIG == 24 typedef float zig_f32; @@ -1993,7 +2825,9 @@ typedef double zig_f32; #define zig_make_f32(fp, repr) fp #elif LDBL_MANT_DIG == 24 #define zig_bitSizeOf_c_longdouble 32 -typedef uint32_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f32 zig_repr_c_longdouble; +#endif typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l #elif FLT32_MANT_DIG == 24 @@ -2007,21 +2841,24 @@ typedef int32_t zig_f32; #define zig_make_f32(fp, repr) repr #undef zig_make_special_f32 #define zig_make_special_f32(sign, name, arg, repr) repr -#undef zig_make_special_constant_f32 -#define zig_make_special_constant_f32(sign, name, arg, repr) repr +#undef zig_init_special_f32 +#define zig_init_special_f32(sign, name, arg, repr) repr #endif #define zig_has_f64 1 #define zig_bitSizeOf_f64 64 +typedef int64_t zig_repr_f64; #define zig_libc_name_f64(name) name #if _MSC_VER #ifdef ZIG_TARGET_ABI_MSVC #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f64 zig_repr_c_longdouble; +#endif #endif -#define zig_make_special_constant_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, ) +#define zig_init_special_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, ) #else /* _MSC_VER */ -#define zig_make_special_constant_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) +#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif /* _MSC_VER */ #if FLT_MANT_DIG == 53 typedef float zig_f64; @@ -2031,7 +2868,9 @@ typedef double zig_f64; #define zig_make_f64(fp, repr) fp #elif LDBL_MANT_DIG == 53 #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f64 zig_repr_c_longdouble; +#endif typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l #elif FLT64_MANT_DIG == 53 @@ -2048,14 +2887,15 @@ typedef int64_t zig_f64; #define zig_make_f64(fp, repr) repr #undef zig_make_special_f64 #define zig_make_special_f64(sign, name, arg, repr) repr -#undef zig_make_special_constant_f64 -#define zig_make_special_constant_f64(sign, name, arg, repr) repr +#undef zig_init_special_f64 +#define zig_init_special_f64(sign, name, arg, repr) repr #endif #define zig_has_f80 1 #define zig_bitSizeOf_f80 80 +typedef zig_i128 zig_repr_f80; #define zig_libc_name_f80(name) __##name##x -#define zig_make_special_constant_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) +#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) #if FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f @@ -2064,7 +2904,9 @@ typedef double zig_f80; #define zig_make_f80(fp, repr) fp #elif LDBL_MANT_DIG == 64 #define zig_bitSizeOf_c_longdouble 80 -typedef zig_u128 zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f80 zig_repr_c_longdouble; +#endif typedef long double zig_f80; #define zig_make_f80(fp, repr) fp##l #elif FLT80_MANT_DIG == 64 @@ -2084,14 +2926,15 @@ typedef zig_i128 zig_f80; #define zig_make_f80(fp, repr) repr #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr -#undef zig_make_special_constant_f80 -#define zig_make_special_constant_f80(sign, name, arg, repr) repr +#undef zig_init_special_f80 +#define zig_init_special_f80(sign, name, arg, repr) repr #endif #define zig_has_f128 1 #define zig_bitSizeOf_f128 128 +typedef zig_i128 zig_repr_f128; #define zig_libc_name_f128(name) name##q -#define zig_make_special_constant_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) +#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f @@ -2100,7 +2943,9 @@ typedef double zig_f128; #define zig_make_f128(fp, repr) fp #elif LDBL_MANT_DIG == 113 #define zig_bitSizeOf_c_longdouble 128 -typedef zig_u128 zig_repr_c_longdouble; +#ifndef ZIG_TARGET_ABI_MSVC +typedef zig_repr_f128 zig_repr_c_longdouble; +#endif typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l #elif FLT128_MANT_DIG == 113 @@ -2122,63 +2967,44 @@ typedef zig_i128 zig_f128; #define zig_make_f128(fp, repr) repr #undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr -#undef zig_make_special_constant_f128 -#define zig_make_special_constant_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 +#define zig_init_special_f128(sign, name, arg, repr) repr #endif -#define zig_has_c_longdouble 1 - -#ifdef ZIG_TARGET_ABI_MSVC -#define zig_libc_name_c_longdouble(name) name -#else -#define zig_libc_name_c_longdouble(name) name##l -#endif - -#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) zig_make_special_c_longdouble(sign, name, arg, repr) #ifdef zig_bitSizeOf_c_longdouble +#define zig_has_c_longdouble 1 #ifdef ZIG_TARGET_ABI_MSVC #undef zig_bitSizeOf_c_longdouble #define zig_bitSizeOf_c_longdouble 64 -typedef uint64_t zig_repr_c_longdouble; typedef zig_f64 zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) fp +typedef zig_repr_f64 zig_repr_c_longdouble; #else typedef long double zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) fp##l #endif #else /* zig_bitSizeOf_c_longdouble */ -#undef zig_has_c_longdouble #define zig_has_c_longdouble 0 -#define zig_bitSizeOf_c_longdouble 80 -typedef zig_u128 zig_repr_c_longdouble; -#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80 #define zig_bitSizeOf_repr_c_longdouble 128 -typedef zig_i128 zig_c_longdouble; -#define zig_make_c_longdouble(fp, repr) repr -#undef zig_make_special_c_longdouble -#define zig_make_special_c_longdouble(sign, name, arg, repr) repr -#undef zig_make_special_constant_c_longdouble -#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) repr +typedef zig_f128 zig_c_longdouble; +typedef zig_repr_f128 zig_repr_c_longdouble; #endif /* zig_bitSizeOf_c_longdouble */ #if !zig_has_float_builtins -#define zig_float_from_repr(Type, ReprType) \ - static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \ +#define zig_float_from_repr(Type) \ + static inline zig_##Type zig_float_from_repr_##Type(zig_repr_##Type repr) { \ zig_##Type result; \ memcpy(&result, &repr, sizeof(result)); \ return result; \ } -zig_float_from_repr(f16, uint16_t) -zig_float_from_repr(f32, uint32_t) -zig_float_from_repr(f64, uint64_t) -zig_float_from_repr(f80, zig_u128) -zig_float_from_repr(f128, zig_u128) -zig_float_from_repr(c_longdouble, zig_repr_c_longdouble) +zig_float_from_repr(f16) +zig_float_from_repr(f32) +zig_float_from_repr(f64) +zig_float_from_repr(f80) +zig_float_from_repr(f128) #endif #define zig_cast_f16 (zig_f16) @@ -2187,11 +3013,9 @@ zig_float_from_repr(c_longdouble, zig_repr_c_longdouble) #if _MSC_VER && !zig_has_f128 #define zig_cast_f80 -#define zig_cast_c_longdouble #define zig_cast_f128 #else #define zig_cast_f80 (zig_f80) -#define zig_cast_c_longdouble (zig_c_longdouble) #define zig_cast_f128 (zig_f128) #endif @@ -2320,7 +3144,6 @@ zig_float_builtins(f32) zig_float_builtins(f64) zig_float_builtins(f80) zig_float_builtins(f128) -zig_float_builtins(c_longdouble) #if _MSC_VER && (_M_IX86 || _M_X64) |
