| ... | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const is_test = builtin.is_test; |
| 4 | 4 | const Log2Int = std.math.Log2Int; |
| 5 | const HalveInt = @import("common.zig").HalveInt; |
| 5 | 6 | |
| 6 | 7 | const lo = switch (builtin.cpu.arch.endian()) { |
| 7 | 8 | .Big => 1, |
| ... | ... | @@ -9,19 +10,10 @@ const lo = switch (builtin.cpu.arch.endian()) { |
| 9 | 10 | }; |
| 10 | 11 | const hi = 1 - lo; |
| 11 | 12 | |
| 12 | | fn HalfInt(comptime T: type) type { |
| 13 | | std.debug.assert(@typeInfo(T) == .Int); |
| 14 | | std.debug.assert(@bitSizeOf(T) % 2 == 0); |
| 15 | | return std.meta.Int(.unsigned, @bitSizeOf(T) / 2); |
| 16 | | } |
| 17 | | |
| 18 | | // Performs division of a double-word specified in its single-word components. Most commonly used |
| 19 | | // for computing u128 bit divisions in terms of 64-bit integers. |
| 20 | | // |
| 21 | | // q = U / v |
| 22 | | // r = U % v |
| 23 | | // where U = (u1 | u0) |
| 13 | // Let _u1 and _u0 be the high and low limbs of U respectively. |
| 14 | // Returns U / v_ and sets r = U % v_. |
| 24 | 15 | fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T { |
| 16 | const HalfT = HalveInt(T, false).HalfT; |
| 25 | 17 | @setRuntimeSafety(is_test); |
| 26 | 18 | var v = v_; |
| 27 | 19 | |
| ... | ... | @@ -43,11 +35,11 @@ fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T { |
| 43 | 35 | |
| 44 | 36 | // Break divisor up into two 32-bit digits |
| 45 | 37 | const vn1 = v >> (@bitSizeOf(T) / 2); |
| 46 | | const vn0 = v & std.math.maxInt(HalfInt(T)); |
| 38 | const vn0 = v & std.math.maxInt(HalfT); |
| 47 | 39 | |
| 48 | 40 | // Break right half of dividend into two digits |
| 49 | 41 | const un1 = un10 >> (@bitSizeOf(T) / 2); |
| 50 | | const un0 = un10 & std.math.maxInt(HalfInt(T)); |
| 42 | const un0 = un10 & std.math.maxInt(HalfT); |
| 51 | 43 | |
| 52 | 44 | // Compute the first quotient digit, q1 |
| 53 | 45 | var q1 = un64 / vn1; |
| ... | ... | @@ -79,7 +71,7 @@ fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T { |
| 79 | 71 | |
| 80 | 72 | fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T { |
| 81 | 73 | @setRuntimeSafety(is_test); |
| 82 | | if (T == u64 and builtin.target.cpu.arch == .x86_64) { |
| 74 | if (T == u64 and builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag != .windows) { |
| 83 | 75 | var rem: T = undefined; |
| 84 | 76 | const quo = asm ( |
| 85 | 77 | \\divq %[v] |
| ... | ... | @@ -96,10 +88,10 @@ fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T { |
| 96 | 88 | } |
| 97 | 89 | } |
| 98 | 90 | |
| 99 | | // return q = a / b, *r = a % b |
| 91 | // Returns a_ / b_ and sets maybe_rem = a_ % b. |
| 100 | 92 | pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T { |
| 101 | 93 | @setRuntimeSafety(is_test); |
| 102 | | const HalfT = HalfInt(T); |
| 94 | const HalfT = HalveInt(T, false).HalfT; |
| 103 | 95 | const SignedT = std.meta.Int(.signed, @bitSizeOf(T)); |
| 104 | 96 | |
| 105 | 97 | if (b_ > a_) { |
| ... | ... | @@ -141,8 +133,8 @@ pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T { |
| 141 | 133 | for (0..shift + 1) |_| { |
| 142 | 134 | q[lo] <<= 1; |
| 143 | 135 | // Branchless version of: |
| 144 | | // if (a >= b) { |
| 145 | | // a -= b; |
| 136 | // if (af >= bf) { |
| 137 | // af -= bf; |
| 146 | 138 | // q[lo] |= 1; |
| 147 | 139 | // } |
| 148 | 140 | const s = @bitCast(SignedT, bf -% af -% 1) >> (@bitSizeOf(T) - 1); |