From 9dfb917c200eb97223bdfcda93c08e509fe1362f Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Fri, 28 Aug 2020 08:58:51 -0400 Subject: [PATCH 1/9] std: Add std.math.divCeil --- lib/std/math.zig | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/std/math.zig b/lib/std/math.zig index a76f0a391d..733d6b74b4 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -621,6 +621,26 @@ fn testDivFloor() void { testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); } +pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { + @setRuntimeSafety(false); + if (numerator <= 0) return divTrunc(T, numerator, denominator); + return (try divFloor(T, numerator - 1, denominator)) + 1; +} + +test "math.divCeil" { + testDivCeil(); + comptime testDivCeil(); +} +fn testDivCeil() void { + testing.expect((divCeil(i32, 5, 3) catch unreachable) == 2); + testing.expect((divCeil(i32, -5, 3) catch unreachable) == -1); + testing.expectError(error.DivisionByZero, divCeil(i8, -5, 0)); + testing.expectError(error.Overflow, divCeil(i8, -128, -1)); + + testing.expect((divCeil(f32, 5.0, 3.0) catch unreachable) == 2.0); + testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); +} + pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (denominator == 0) return error.DivisionByZero; From aacfef17d5273abeb50cb41d5f5687408d6458b7 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Fri, 28 Aug 2020 09:48:40 -0400 Subject: [PATCH 2/9] std.math.divCeil: handle floats correctly --- lib/std/math.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/math.zig b/lib/std/math.zig index 733d6b74b4..3daf643a79 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -624,6 +624,7 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (numerator <= 0) return divTrunc(T, numerator, denominator); + if (@typeInfo(T) == .Float) return @ceil(numerator / denominator); return (try divFloor(T, numerator - 1, denominator)) + 1; } From 14b6fb88fb98580f09fc9092493d537ef3810d77 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Fri, 28 Aug 2020 09:55:50 -0400 Subject: [PATCH 3/9] std.math.divCeil: handle floats correctlier --- lib/std/math.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index 3daf643a79..fef33ead9b 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -624,7 +624,10 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (numerator <= 0) return divTrunc(T, numerator, denominator); - if (@typeInfo(T) == .Float) return @ceil(numerator / denominator); + if (@typeInfo(T) == .Float) { + if (denominator == 0) return error.DivisionByZero; + return @ceil(numerator / denominator); + } return (try divFloor(T, numerator - 1, denominator)) + 1; } From f577d12fbc6a5136b238b4d8e7e361578a66ddd6 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Fri, 28 Aug 2020 11:20:42 -0400 Subject: [PATCH 4/9] std.math.divCeil: conform to more test cases --- lib/std/math.zig | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index fef33ead9b..03a945163a 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -623,12 +623,16 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (numerator <= 0) return divTrunc(T, numerator, denominator); - if (@typeInfo(T) == .Float) { - if (denominator == 0) return error.DivisionByZero; - return @ceil(numerator / denominator); + if (denominator == 0) return error.DivisionByZero; + if (@typeInfo(T) == .Float) return @ceil(numerator / denominator); + if (T.is_signed and numerator < 0 and denominator < 0) { + if (numerator == minInt(T) and denominator == -1) + return error.Overflow; + return @divFloor(numerator + 1, denominator) + 1; } - return (try divFloor(T, numerator - 1, denominator)) + 1; + if (numerator > 0 and denominator > 0) + return @divFloor(numerator - 1, denominator) + 1; + return @divTrunc(numerator, denominator); } test "math.divCeil" { @@ -638,11 +642,18 @@ test "math.divCeil" { fn testDivCeil() void { testing.expect((divCeil(i32, 5, 3) catch unreachable) == 2); testing.expect((divCeil(i32, -5, 3) catch unreachable) == -1); + testing.expect((divCeil(i32, 5, -3) catch unreachable) == -1); + testing.expect((divCeil(i32, -5, -3) catch unreachable) == 2); + testing.expect((divCeil(i32, 0, 5) catch unreachable) == 0); + testing.expect((divCeil(u32, 0, 5) catch unreachable) == 0); testing.expectError(error.DivisionByZero, divCeil(i8, -5, 0)); testing.expectError(error.Overflow, divCeil(i8, -128, -1)); + testing.expect((divCeil(f32, 0.0, 5.0) catch unreachable) == 0.0); testing.expect((divCeil(f32, 5.0, 3.0) catch unreachable) == 2.0); testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); + testing.expect((divCeil(f32, 5.0, -3.0) catch unreachable) == -1.0); + testing.expect((divCeil(f32, -5.0, -3.0) catch unreachable) == 2.0); } pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { From 933bfcff6483897a6fcf24f38e0571d2ae960441 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Sat, 29 Aug 2020 00:21:17 -0400 Subject: [PATCH 5/9] std.math.divCeil: support comptime_int/float --- lib/std/math.zig | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index 03a945163a..f5aa9e4b36 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -624,15 +624,21 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (denominator == 0) return error.DivisionByZero; - if (@typeInfo(T) == .Float) return @ceil(numerator / denominator); - if (T.is_signed and numerator < 0 and denominator < 0) { - if (numerator == minInt(T) and denominator == -1) - return error.Overflow; - return @divFloor(numerator + 1, denominator) + 1; + const info = @typeInfo(T); + switch (info) { + .ComptimeFloat, .Float => return @ceil(numerator / denominator), + .ComptimeInt, .Int => { + if (numerator < 0 and denominator < 0) { + if (info == .Int and numerator == minInt(T) and denominator == -1) + return error.Overflow; + return @divFloor(numerator + 1, denominator) + 1; + } + if (numerator > 0 and denominator > 0) + return @divFloor(numerator - 1, denominator) + 1; + return @divTrunc(numerator, denominator); + }, + else => @compileError("divCeil unsupported on " ++ @typeName(T)), } - if (numerator > 0 and denominator > 0) - return @divFloor(numerator - 1, denominator) + 1; - return @divTrunc(numerator, denominator); } test "math.divCeil" { @@ -654,6 +660,18 @@ fn testDivCeil() void { testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); testing.expect((divCeil(f32, 5.0, -3.0) catch unreachable) == -1.0); testing.expect((divCeil(f32, -5.0, -3.0) catch unreachable) == 2.0); + + testing.expect((divCeil(comptime_int, 23, 4) catch unreachable) == 6); + testing.expect((divCeil(comptime_int, -23, 4) catch unreachable) == -5); + testing.expect((divCeil(comptime_int, 23, -4) catch unreachable) == -5); + testing.expect((divCeil(comptime_int, -23, -4) catch unreachable) == 6); + testing.expectError(error.DivisionByZero, divCeil(comptime_int, 23, 0)); + + testing.expect((divCeil(comptime_float, 23.0, 4.0) catch unreachable) == 6.0); + testing.expect((divCeil(comptime_float, -23.0, 4.0) catch unreachable) == -5.0); + testing.expect((divCeil(comptime_float, 23.0, -4.0) catch unreachable) == -5.0); + testing.expect((divCeil(comptime_float, -23.0, -4.0) catch unreachable) == 6.0); + testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); } pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { From 49e67ce0e8a15e3701e01395c112c4e1ae331972 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Sat, 29 Aug 2020 00:31:49 -0400 Subject: [PATCH 6/9] std.math.divCeil: move compile error to top --- lib/std/math.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index f5aa9e4b36..a66d47412d 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -623,7 +623,10 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (denominator == 0) return error.DivisionByZero; + if (!(comptime std.meta.trait.isNumber(T))) + @compileError("divCeil unsupported on " ++ @typeName(T)); + if (denominator == 0) + return error.DivisionByZero; const info = @typeInfo(T); switch (info) { .ComptimeFloat, .Float => return @ceil(numerator / denominator), @@ -637,7 +640,7 @@ pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { return @divFloor(numerator - 1, denominator) + 1; return @divTrunc(numerator, denominator); }, - else => @compileError("divCeil unsupported on " ++ @typeName(T)), + else => unreachable, } } From 340871f06105830087dd8e254e604892f08bccc7 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Sat, 29 Aug 2020 00:37:10 -0400 Subject: [PATCH 7/9] std.math.divCeil: move compile error back down --- lib/std/math.zig | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index a66d47412d..4f640ef652 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -623,10 +623,7 @@ fn testDivFloor() void { pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); - if (!(comptime std.meta.trait.isNumber(T))) - @compileError("divCeil unsupported on " ++ @typeName(T)); - if (denominator == 0) - return error.DivisionByZero; + if (comptime std.meta.trait.isNumber(T) and denominator == 0) return error.DivisionByZero; const info = @typeInfo(T); switch (info) { .ComptimeFloat, .Float => return @ceil(numerator / denominator), @@ -640,7 +637,7 @@ pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { return @divFloor(numerator - 1, denominator) + 1; return @divTrunc(numerator, denominator); }, - else => unreachable, + else => @compileError("divCeil unsupported on " ++ @typeName(T)), } } From 552e2bf7587edd73c2396e36c4167ad1ecfc6de6 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Sat, 29 Aug 2020 02:32:54 -0400 Subject: [PATCH 8/9] std.math.divCeil: use expectEqual for tests --- lib/std/math.zig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index 4f640ef652..653df13ee0 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -646,31 +646,31 @@ test "math.divCeil" { comptime testDivCeil(); } fn testDivCeil() void { - testing.expect((divCeil(i32, 5, 3) catch unreachable) == 2); - testing.expect((divCeil(i32, -5, 3) catch unreachable) == -1); - testing.expect((divCeil(i32, 5, -3) catch unreachable) == -1); - testing.expect((divCeil(i32, -5, -3) catch unreachable) == 2); - testing.expect((divCeil(i32, 0, 5) catch unreachable) == 0); - testing.expect((divCeil(u32, 0, 5) catch unreachable) == 0); + testing.expectEqual(divCeil(i32, 5, 3) catch unreachable, 2); + testing.expectEqual(divCeil(i32, -5, 3) catch unreachable, -1); + testing.expectEqual(divCeil(i32, 5, -3) catch unreachable, -1); + testing.expectEqual(divCeil(i32, -5, -3) catch unreachable, 2); + testing.expectEqual(divCeil(i32, 0, 5) catch unreachable, 0); + testing.expectEqual(divCeil(u32, 0, 5) catch unreachable, 0); testing.expectError(error.DivisionByZero, divCeil(i8, -5, 0)); testing.expectError(error.Overflow, divCeil(i8, -128, -1)); - testing.expect((divCeil(f32, 0.0, 5.0) catch unreachable) == 0.0); - testing.expect((divCeil(f32, 5.0, 3.0) catch unreachable) == 2.0); - testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); - testing.expect((divCeil(f32, 5.0, -3.0) catch unreachable) == -1.0); - testing.expect((divCeil(f32, -5.0, -3.0) catch unreachable) == 2.0); + testing.expectEqual(divCeil(f32, 0.0, 5.0) catch unreachable, 0.0); + testing.expectEqual(divCeil(f32, 5.0, 3.0) catch unreachable, 2.0); + testing.expectEqual(divCeil(f32, -5.0, 3.0) catch unreachable, -1.0); + testing.expectEqual(divCeil(f32, 5.0, -3.0) catch unreachable, -1.0); + testing.expectEqual(divCeil(f32, -5.0, -3.0) catch unreachable, 2.0); - testing.expect((divCeil(comptime_int, 23, 4) catch unreachable) == 6); - testing.expect((divCeil(comptime_int, -23, 4) catch unreachable) == -5); - testing.expect((divCeil(comptime_int, 23, -4) catch unreachable) == -5); - testing.expect((divCeil(comptime_int, -23, -4) catch unreachable) == 6); + testing.expectEqual(divCeil(comptime_int, 23, 4) catch unreachable, 6); + testing.expectEqual(divCeil(comptime_int, -23, 4) catch unreachable, -5); + testing.expectEqual(divCeil(comptime_int, 23, -4) catch unreachable, -5); + testing.expectEqual(divCeil(comptime_int, -23, -4) catch unreachable, 6); testing.expectError(error.DivisionByZero, divCeil(comptime_int, 23, 0)); - testing.expect((divCeil(comptime_float, 23.0, 4.0) catch unreachable) == 6.0); - testing.expect((divCeil(comptime_float, -23.0, 4.0) catch unreachable) == -5.0); - testing.expect((divCeil(comptime_float, 23.0, -4.0) catch unreachable) == -5.0); - testing.expect((divCeil(comptime_float, -23.0, -4.0) catch unreachable) == 6.0); + testing.expectEqual(divCeil(comptime_float, 23.0, 4.0) catch unreachable, 6.0); + testing.expectEqual(divCeil(comptime_float, -23.0, 4.0) catch unreachable, -5.0); + testing.expectEqual(divCeil(comptime_float, 23.0, -4.0) catch unreachable, -5.0); + testing.expectEqual(divCeil(comptime_float, -23.0, -4.0) catch unreachable, 6.0); testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); } From e496485af4fe998a80564082fd7ea4556ed549e1 Mon Sep 17 00:00:00 2001 From: Kate Tsuyu Date: Sat, 29 Aug 2020 03:07:36 -0400 Subject: [PATCH 9/9] std.math.divCeil: fix expectEqual argument order --- lib/std/math.zig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/std/math.zig b/lib/std/math.zig index 653df13ee0..e815bec61c 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -646,31 +646,31 @@ test "math.divCeil" { comptime testDivCeil(); } fn testDivCeil() void { - testing.expectEqual(divCeil(i32, 5, 3) catch unreachable, 2); - testing.expectEqual(divCeil(i32, -5, 3) catch unreachable, -1); - testing.expectEqual(divCeil(i32, 5, -3) catch unreachable, -1); - testing.expectEqual(divCeil(i32, -5, -3) catch unreachable, 2); - testing.expectEqual(divCeil(i32, 0, 5) catch unreachable, 0); - testing.expectEqual(divCeil(u32, 0, 5) catch unreachable, 0); + testing.expectEqual(@as(i32, 2), divCeil(i32, 5, 3) catch unreachable); + testing.expectEqual(@as(i32, -1), divCeil(i32, -5, 3) catch unreachable); + testing.expectEqual(@as(i32, -1), divCeil(i32, 5, -3) catch unreachable); + testing.expectEqual(@as(i32, 2), divCeil(i32, -5, -3) catch unreachable); + testing.expectEqual(@as(i32, 0), divCeil(i32, 0, 5) catch unreachable); + testing.expectEqual(@as(u32, 0), divCeil(u32, 0, 5) catch unreachable); testing.expectError(error.DivisionByZero, divCeil(i8, -5, 0)); testing.expectError(error.Overflow, divCeil(i8, -128, -1)); - testing.expectEqual(divCeil(f32, 0.0, 5.0) catch unreachable, 0.0); - testing.expectEqual(divCeil(f32, 5.0, 3.0) catch unreachable, 2.0); - testing.expectEqual(divCeil(f32, -5.0, 3.0) catch unreachable, -1.0); - testing.expectEqual(divCeil(f32, 5.0, -3.0) catch unreachable, -1.0); - testing.expectEqual(divCeil(f32, -5.0, -3.0) catch unreachable, 2.0); + testing.expectEqual(@as(f32, 0.0), divCeil(f32, 0.0, 5.0) catch unreachable); + testing.expectEqual(@as(f32, 2.0), divCeil(f32, 5.0, 3.0) catch unreachable); + testing.expectEqual(@as(f32, -1.0), divCeil(f32, -5.0, 3.0) catch unreachable); + testing.expectEqual(@as(f32, -1.0), divCeil(f32, 5.0, -3.0) catch unreachable); + testing.expectEqual(@as(f32, 2.0), divCeil(f32, -5.0, -3.0) catch unreachable); - testing.expectEqual(divCeil(comptime_int, 23, 4) catch unreachable, 6); - testing.expectEqual(divCeil(comptime_int, -23, 4) catch unreachable, -5); - testing.expectEqual(divCeil(comptime_int, 23, -4) catch unreachable, -5); - testing.expectEqual(divCeil(comptime_int, -23, -4) catch unreachable, 6); + testing.expectEqual(6, divCeil(comptime_int, 23, 4) catch unreachable); + testing.expectEqual(-5, divCeil(comptime_int, -23, 4) catch unreachable); + testing.expectEqual(-5, divCeil(comptime_int, 23, -4) catch unreachable); + testing.expectEqual(6, divCeil(comptime_int, -23, -4) catch unreachable); testing.expectError(error.DivisionByZero, divCeil(comptime_int, 23, 0)); - testing.expectEqual(divCeil(comptime_float, 23.0, 4.0) catch unreachable, 6.0); - testing.expectEqual(divCeil(comptime_float, -23.0, 4.0) catch unreachable, -5.0); - testing.expectEqual(divCeil(comptime_float, 23.0, -4.0) catch unreachable, -5.0); - testing.expectEqual(divCeil(comptime_float, -23.0, -4.0) catch unreachable, 6.0); + testing.expectEqual(6.0, divCeil(comptime_float, 23.0, 4.0) catch unreachable); + testing.expectEqual(-5.0, divCeil(comptime_float, -23.0, 4.0) catch unreachable); + testing.expectEqual(-5.0, divCeil(comptime_float, 23.0, -4.0) catch unreachable); + testing.expectEqual(6.0, divCeil(comptime_float, -23.0, -4.0) catch unreachable); testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); }