| ... | @@ -624,15 +624,21 @@ fn testDivFloor() void { | ... | @@ -624,15 +624,21 @@ fn testDivFloor() void { |
| 624 | pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { | 624 | pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { |
| 625 | @setRuntimeSafety(false); | 625 | @setRuntimeSafety(false); |
| 626 | if (denominator == 0) return error.DivisionByZero; | 626 | if (denominator == 0) return error.DivisionByZero; |
| 627 | if (@typeInfo(T) == .Float) return @ceil(numerator / denominator); | 627 | const info = @typeInfo(T); |
| 628 | if (T.is_signed and numerator < 0 and denominator < 0) { | 628 | switch (info) { |
| 629 | if (numerator == minInt(T) and denominator == -1) | 629 | .ComptimeFloat, .Float => return @ceil(numerator / denominator), |
| 630 | return error.Overflow; | 630 | .ComptimeInt, .Int => { |
| 631 | return @divFloor(numerator + 1, denominator) + 1; | 631 | if (numerator < 0 and denominator < 0) { |
| | 632 | if (info == .Int and numerator == minInt(T) and denominator == -1) |
| | 633 | return error.Overflow; |
| | 634 | return @divFloor(numerator + 1, denominator) + 1; |
| | 635 | } |
| | 636 | if (numerator > 0 and denominator > 0) |
| | 637 | return @divFloor(numerator - 1, denominator) + 1; |
| | 638 | return @divTrunc(numerator, denominator); |
| | 639 | }, |
| | 640 | else => @compileError("divCeil unsupported on " ++ @typeName(T)), |
| 632 | } | 641 | } |
| 633 | if (numerator > 0 and denominator > 0) | | |
| 634 | return @divFloor(numerator - 1, denominator) + 1; | | |
| 635 | return @divTrunc(numerator, denominator); | | |
| 636 | } | 642 | } |
| 637 | | 643 | |
| 638 | test "math.divCeil" { | 644 | test "math.divCeil" { |
| ... | @@ -654,6 +660,18 @@ fn testDivCeil() void { | ... | @@ -654,6 +660,18 @@ fn testDivCeil() void { |
| 654 | testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); | 660 | testing.expect((divCeil(f32, -5.0, 3.0) catch unreachable) == -1.0); |
| 655 | testing.expect((divCeil(f32, 5.0, -3.0) catch unreachable) == -1.0); | 661 | testing.expect((divCeil(f32, 5.0, -3.0) catch unreachable) == -1.0); |
| 656 | testing.expect((divCeil(f32, -5.0, -3.0) catch unreachable) == 2.0); | 662 | testing.expect((divCeil(f32, -5.0, -3.0) catch unreachable) == 2.0); |
| | 663 | |
| | 664 | testing.expect((divCeil(comptime_int, 23, 4) catch unreachable) == 6); |
| | 665 | testing.expect((divCeil(comptime_int, -23, 4) catch unreachable) == -5); |
| | 666 | testing.expect((divCeil(comptime_int, 23, -4) catch unreachable) == -5); |
| | 667 | testing.expect((divCeil(comptime_int, -23, -4) catch unreachable) == 6); |
| | 668 | testing.expectError(error.DivisionByZero, divCeil(comptime_int, 23, 0)); |
| | 669 | |
| | 670 | testing.expect((divCeil(comptime_float, 23.0, 4.0) catch unreachable) == 6.0); |
| | 671 | testing.expect((divCeil(comptime_float, -23.0, 4.0) catch unreachable) == -5.0); |
| | 672 | testing.expect((divCeil(comptime_float, 23.0, -4.0) catch unreachable) == -5.0); |
| | 673 | testing.expect((divCeil(comptime_float, -23.0, -4.0) catch unreachable) == 6.0); |
| | 674 | testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); |
| 657 | } | 675 | } |
| 658 | | 676 | |
| 659 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { | 677 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { |