diff --git a/lib/zig.h b/lib/zig.h index 5929656985a6e45d457172a7c44d4ee3092fce82..5ee8e3dd76e62b55fe5821a5d142cf1ba8b13123 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -1357,10 +1357,10 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; #define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) #define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) -#if _MSC_VER +#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) } -#else +#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) #endif @@ -1421,6 +1421,11 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { return lhs << rhs; } +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +} + static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { return lhs << rhs; } @@ -1496,6 +1501,12 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; } +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { if (rhs == UINT8_C(0)) return lhs; if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; @@ -1527,14 +1538,14 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { } zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); -static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitcast_u128(__multi3(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs))); -} - static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return __multi3(lhs, rhs); } +static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { + return zig_bitcast_u128(zig_mul_i128(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs))); +} + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { return __udivti3(lhs, rhs); @@ -1557,7 +1568,7 @@ static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); - return zig_add_i128(rem, (((lhs.hi ^ rhs.hi) & rem.hi) < INT64_C(0) ? rhs : zig_make_i128(0, 0))); + return zig_add_i128(rem, ((lhs.hi ^ rhs.hi) & rem.hi) < INT64_C(0) ? rhs : zig_make_i128(0, 0)); } static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { @@ -1589,11 +1600,6 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - zig_i128 sign_mask = zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_sub_i128(zig_make_i128(0, 0), zig_make_i128(0, 1)) : zig_make_i128(0, 0); - return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask); -} - static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { return zig_and_u128(val, zig_maxInt_u(128, bits)); } @@ -1716,50 +1722,28 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint #else /* zig_has_int128 */ -static inline bool zig_overflow_u128(bool overflow, zig_u128 full_res, uint8_t bits) { - return overflow || - zig_cmp_u128(full_res, zig_minInt_u(128, bits)) < INT32_C(0) || - zig_cmp_u128(full_res, zig_maxInt_u(128, bits)) > INT32_C(0); -} - -static inline bool zig_overflow_i128(bool overflow, zig_i128 full_res, uint8_t bits) { - return overflow || - zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || - zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); -} - static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - zig_u128 full_res; - bool overflow = - zig_addo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) | - zig_addo_u64(&full_res.hi, full_res.hi, zig_addo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64); - *res = zig_wrap_u128(full_res, bits); - return zig_overflow_u128(overflow, full_res, bits); + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); } -zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int overflow_int; - zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int); - *res = zig_wrap_i128(full_res, bits); - return zig_overflow_i128(overflow_int, full_res, bits); + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - zig_u128 full_res; - bool overflow = - zig_subo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) | - zig_subo_u64(&full_res.hi, full_res.hi, zig_subo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64); - *res = zig_wrap_u128(full_res, bits); - return zig_overflow_u128(overflow, full_res, bits); + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); } -zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int overflow_int; - zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int); - *res = zig_wrap_i128(full_res, bits); - return zig_overflow_i128(overflow_int, full_res, bits); + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { @@ -1772,8 +1756,11 @@ zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); + bool overflow = overflow_int != 0 || + zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || + zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); *res = zig_wrap_i128(full_res, bits); - return zig_overflow_i128(overflow_int, full_res, bits); + return overflow; } #endif /* zig_has_int128 */ @@ -1794,17 +1781,12 @@ static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) >= INT32_C(0)) return zig_cmp_u128(lhs, zig_make_u128(0, 0)) != INT32_C(0) ? zig_maxInt_u(128, bits) : lhs; - -#if zig_has_int128 - return zig_shlo_u128(&res, lhs, (uint8_t)rhs, bits) ? zig_maxInt_u(128, bits) : res; -#else - return zig_shlo_u128(&res, lhs, (uint8_t)rhs.lo, bits) ? zig_maxInt_u(128, bits) : res; -#endif + return zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits) ? zig_maxInt_u(128, bits) : res; } static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { zig_i128 res; - if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, zig_lo_i128(rhs), bits)) return res; + if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_i128(rhs), bits)) return res; return zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); }