| ... | @@ -596,6 +596,59 @@ fn testDivFloor() void { | ... | @@ -596,6 +596,59 @@ fn testDivFloor() void { |
| 596 | testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); | 596 | testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); |
| 597 | } | 597 | } |
| 598 | | 598 | |
| | 599 | pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { |
| | 600 | @setRuntimeSafety(false); |
| | 601 | if (comptime std.meta.trait.isNumber(T) and denominator == 0) return error.DivisionByZero; |
| | 602 | const info = @typeInfo(T); |
| | 603 | switch (info) { |
| | 604 | .ComptimeFloat, .Float => return @ceil(numerator / denominator), |
| | 605 | .ComptimeInt, .Int => { |
| | 606 | if (numerator < 0 and denominator < 0) { |
| | 607 | if (info == .Int and numerator == minInt(T) and denominator == -1) |
| | 608 | return error.Overflow; |
| | 609 | return @divFloor(numerator + 1, denominator) + 1; |
| | 610 | } |
| | 611 | if (numerator > 0 and denominator > 0) |
| | 612 | return @divFloor(numerator - 1, denominator) + 1; |
| | 613 | return @divTrunc(numerator, denominator); |
| | 614 | }, |
| | 615 | else => @compileError("divCeil unsupported on " ++ @typeName(T)), |
| | 616 | } |
| | 617 | } |
| | 618 | |
| | 619 | test "math.divCeil" { |
| | 620 | testDivCeil(); |
| | 621 | comptime testDivCeil(); |
| | 622 | } |
| | 623 | fn testDivCeil() void { |
| | 624 | testing.expectEqual(@as(i32, 2), divCeil(i32, 5, 3) catch unreachable); |
| | 625 | testing.expectEqual(@as(i32, -1), divCeil(i32, -5, 3) catch unreachable); |
| | 626 | testing.expectEqual(@as(i32, -1), divCeil(i32, 5, -3) catch unreachable); |
| | 627 | testing.expectEqual(@as(i32, 2), divCeil(i32, -5, -3) catch unreachable); |
| | 628 | testing.expectEqual(@as(i32, 0), divCeil(i32, 0, 5) catch unreachable); |
| | 629 | testing.expectEqual(@as(u32, 0), divCeil(u32, 0, 5) catch unreachable); |
| | 630 | testing.expectError(error.DivisionByZero, divCeil(i8, -5, 0)); |
| | 631 | testing.expectError(error.Overflow, divCeil(i8, -128, -1)); |
| | 632 | |
| | 633 | testing.expectEqual(@as(f32, 0.0), divCeil(f32, 0.0, 5.0) catch unreachable); |
| | 634 | testing.expectEqual(@as(f32, 2.0), divCeil(f32, 5.0, 3.0) catch unreachable); |
| | 635 | testing.expectEqual(@as(f32, -1.0), divCeil(f32, -5.0, 3.0) catch unreachable); |
| | 636 | testing.expectEqual(@as(f32, -1.0), divCeil(f32, 5.0, -3.0) catch unreachable); |
| | 637 | testing.expectEqual(@as(f32, 2.0), divCeil(f32, -5.0, -3.0) catch unreachable); |
| | 638 | |
| | 639 | testing.expectEqual(6, divCeil(comptime_int, 23, 4) catch unreachable); |
| | 640 | testing.expectEqual(-5, divCeil(comptime_int, -23, 4) catch unreachable); |
| | 641 | testing.expectEqual(-5, divCeil(comptime_int, 23, -4) catch unreachable); |
| | 642 | testing.expectEqual(6, divCeil(comptime_int, -23, -4) catch unreachable); |
| | 643 | testing.expectError(error.DivisionByZero, divCeil(comptime_int, 23, 0)); |
| | 644 | |
| | 645 | testing.expectEqual(6.0, divCeil(comptime_float, 23.0, 4.0) catch unreachable); |
| | 646 | testing.expectEqual(-5.0, divCeil(comptime_float, -23.0, 4.0) catch unreachable); |
| | 647 | testing.expectEqual(-5.0, divCeil(comptime_float, 23.0, -4.0) catch unreachable); |
| | 648 | testing.expectEqual(6.0, divCeil(comptime_float, -23.0, -4.0) catch unreachable); |
| | 649 | testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); |
| | 650 | } |
| | 651 | |
| 599 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { | 652 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { |
| 600 | @setRuntimeSafety(false); | 653 | @setRuntimeSafety(false); |
| 601 | if (denominator == 0) return error.DivisionByZero; | 654 | if (denominator == 0) return error.DivisionByZero; |