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 a76f0a391dcc152b06e9bdf86c1e7321cd018787..733d6b74b4b715a02a1d4e6c9787b94d151899da 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; -- 2.54.0 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 733d6b74b4b715a02a1d4e6c9787b94d151899da..3daf643a79bb322699e39653757a9bbdfed7dc66 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; } -- 2.54.0 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 3daf643a79bb322699e39653757a9bbdfed7dc66..fef33ead9b5c57f0a1340a272821b1d0e1c96e1e 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; } -- 2.54.0 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 fef33ead9b5c57f0a1340a272821b1d0e1c96e1e..03a945163a61667bffcc6be0245bb9e598fc347d 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 { -- 2.54.0 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 03a945163a61667bffcc6be0245bb9e598fc347d..f5aa9e4b36cbc137c5556c635b42fcc2e7b02d96 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 { -- 2.54.0 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 f5aa9e4b36cbc137c5556c635b42fcc2e7b02d96..a66d47412d1b9f71d03e4aa4dae520e46dc6bf04 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, } } -- 2.54.0 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 a66d47412d1b9f71d03e4aa4dae520e46dc6bf04..4f640ef652558d3e9c70d7c22d5b3998a63877a9 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)), } } -- 2.54.0 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 4f640ef652558d3e9c70d7c22d5b3998a63877a9..653df13ee0e7095f701d4d2fe525837fa0bf1403 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)); } -- 2.54.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 653df13ee0e7095f701d4d2fe525837fa0bf1403..e815bec61c2ec8ec16b21d418f6788ffda44dc87 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)); } -- 2.54.0