authorgravatar for casarin.filippo17@gmail.comFilippo Casarin <casarin.filippo17@gmail.com> 2021-03-24 20:59:15+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-10 10:20:09-07:00
log05380a11a426ce22a1a27f47d9f9371a72a35e24
tree147ea450a01d2f40d7892ba3825d3a99bc149934
parent4a3ac16711b41d90e0666f478e3085f764c83208

std.math.sqrt_int: fixed odd size integers types


1 files changed, 26 insertions(+), 31 deletions(-)

lib/std/math/sqrt.zig+26-31
...@@ -39,55 +39,50 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {...@@ -39,55 +39,50 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {
39}39}
4040
41fn sqrt_int(comptime T: type, value: T) Sqrt(T) {41fn sqrt_int(comptime T: type, value: T) Sqrt(T) {
42 switch (T) {42 if (@typeInfo(T).Int.bits <= 2) {
43 u0 => return 0,43 return if (value == 0) 0 else 1; // shortcut for small number of bits to simplify general case
44 u1 => return value,44 } else {
45 else => {},45 var op = value;
46 }46 var res: T = 0;
4747 var one: T = 1 << ((@typeInfo(T).Int.bits - 1) & -2); // highest power of four that fits into T
48 var op = value;
49 var res: T = 0;
50 var one: T = 1 << (@typeInfo(T).Int.bits - 2);
5148
52 // "one" starts at the highest power of four <= than the argument.49 // "one" starts at the highest power of four <= than the argument.
53 while (one > op) {50 while (one > op) {
54 one >>= 2;51 one >>= 2;
55 }52 }
5653
57 while (one != 0) {54 while (one != 0) {
58 if (op >= res + one) {55 var c = op >= res + one;
59 op -= res + one;56 if (c) op -= res + one;
60 res += 2 * one;57 res >>= 1;
58 if (c) res += one;
59 one >>= 2;
61 }60 }
62 res >>= 1;
63 one >>= 2;
64 }
6561
66 const ResultType = Sqrt(T);62 return @intCast(Sqrt(T), res);
67 return @intCast(ResultType, res);63 }
68}64}
6965
70test "math.sqrt_int" {66test "math.sqrt_int" {
71 try expect(sqrt_int(u0, 0) == 0);
72 try expect(sqrt_int(u1, 1) == 1);
73 try expect(sqrt_int(u32, 3) == 1);67 try expect(sqrt_int(u32, 3) == 1);
74 try expect(sqrt_int(u32, 4) == 2);68 try expect(sqrt_int(u32, 4) == 2);
75 try expect(sqrt_int(u32, 5) == 2);69 try expect(sqrt_int(u32, 5) == 2);
76 try expect(sqrt_int(u32, 8) == 2);70 try expect(sqrt_int(u32, 8) == 2);
77 try expect(sqrt_int(u32, 9) == 3);71 try expect(sqrt_int(u32, 9) == 3);
78 try expect(sqrt_int(u32, 10) == 3);72 try expect(sqrt_int(u32, 10) == 3);
73
74 try expect(sqrt_int(u0, 0) == 0);
75 try expect(sqrt_int(u1, 1) == 1);
76 try expect(sqrt_int(u2, 3) == 1);
77 try expect(sqrt_int(u3, 4) == 2);
78 try expect(sqrt_int(u4, 8) == 2);
79 try expect(sqrt_int(u4, 9) == 3);
79}80}
8081
81/// Returns the return type `sqrt` will return given an operand of type `T`.82/// Returns the return type `sqrt` will return given an operand of type `T`.
82pub fn Sqrt(comptime T: type) type {83pub fn Sqrt(comptime T: type) type {
83 return switch (@typeInfo(T)) {84 return switch (@typeInfo(T)) {
84 .Int => |int| {85 .Int => |int| std.meta.Int(.unsigned, (int.bits + 1) / 2),
85 return switch (int.bits) {
86 0 => u0,
87 1 => u1,
88 else => std.meta.Int(.unsigned, int.bits / 2),
89 };
90 },
91 else => T,86 else => T,
92 };87 };
93}88}