/
muloti4.zig
55 lines (46 loc) · 1.27 KB
/
muloti4.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const udivmod = @import("udivmod.zig").udivmod;
const builtin = @import("builtin");
const compiler_rt = @import("../compiler_rt.zig");
pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
@setRuntimeSafety(builtin.is_test);
const min = @bitCast(i128, u128(1 << (i128.bit_count - 1)));
const max = ~min;
overflow.* = 0;
const r = a *% b;
if (a == min) {
if (b != 0 and b != 1) {
overflow.* = 1;
}
return r;
}
if (b == min) {
if (a != 0 and a != 1) {
overflow.* = 1;
}
return r;
}
const sa = a >> (i128.bit_count - 1);
const abs_a = (a ^ sa) -% sa;
const sb = b >> (i128.bit_count - 1);
const abs_b = (b ^ sb) -% sb;
if (abs_a < 2 or abs_b < 2) {
return r;
}
if (sa == sb) {
if (abs_a > @divFloor(max, abs_b)) {
overflow.* = 1;
}
} else {
if (abs_a > @divFloor(min, -abs_b)) {
overflow.* = 1;
}
}
return r;
}
pub extern fn __muloti4_windows_x86_64(a: *const i128, b: *const i128, overflow: *c_int) void {
@setRuntimeSafety(builtin.is_test);
compiler_rt.setXmm0(i128, __muloti4(a.*, b.*, overflow));
}
test "import muloti4" {
_ = @import("muloti4_test.zig");
}