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)) {
3939}
4040
4141fn sqrt_int(comptime T: type, value: T) Sqrt(T) {
42 switch (T) {
43 u0 => return 0,
44 u1 => return value,
45 else => {},
46 }
47
48 var op = value;
49 var res: T = 0;
50 var one: T = 1 << (@typeInfo(T).Int.bits - 2);
42 if (@typeInfo(T).Int.bits <= 2) {
43 return if (value == 0) 0 else 1; // shortcut for small number of bits to simplify general case
44 } else {
45 var op = value;
46 var res: T = 0;
47 var one: T = 1 << ((@typeInfo(T).Int.bits - 1) & -2); // highest power of four that fits into T
5148
52 // "one" starts at the highest power of four <= than the argument.
53 while (one > op) {
54 one >>= 2;
55 }
49 // "one" starts at the highest power of four <= than the argument.
50 while (one > op) {
51 one >>= 2;
52 }
5653
57 while (one != 0) {
58 if (op >= res + one) {
59 op -= res + one;
60 res += 2 * one;
54 while (one != 0) {
55 var c = op >= res + one;
56 if (c) op -= res + one;
57 res >>= 1;
58 if (c) res += one;
59 one >>= 2;
6160 }
62 res >>= 1;
63 one >>= 2;
64 }
6561
66 const ResultType = Sqrt(T);
67 return @intCast(ResultType, res);
62 return @intCast(Sqrt(T), res);
63 }
6864}
6965
7066test "math.sqrt_int" {
71 try expect(sqrt_int(u0, 0) == 0);
72 try expect(sqrt_int(u1, 1) == 1);
7367 try expect(sqrt_int(u32, 3) == 1);
7468 try expect(sqrt_int(u32, 4) == 2);
7569 try expect(sqrt_int(u32, 5) == 2);
7670 try expect(sqrt_int(u32, 8) == 2);
7771 try expect(sqrt_int(u32, 9) == 3);
7872 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);
7980}
8081
8182/// Returns the return type `sqrt` will return given an operand of type `T`.
8283pub fn Sqrt(comptime T: type) type {
8384 return switch (@typeInfo(T)) {
84 .Int => |int| {
85 return switch (int.bits) {
86 0 => u0,
87 1 => u1,
88 else => std.meta.Int(.unsigned, int.bits / 2),
89 };
90 },
85 .Int => |int| std.meta.Int(.unsigned, (int.bits + 1) / 2),
9186 else => T,
9287 };
9388}