| ... | ... | @@ -696,6 +696,76 @@ test "math.floorPowerOfTwo" { |
| 696 | 696 | comptime testFloorPowerOfTwo(); |
| 697 | 697 | } |
| 698 | 698 | |
| 699 | fn testFloorPowerOfTwo() void { |
| 700 | testing.expect(floorPowerOfTwo(u32, 63) == 32); |
| 701 | testing.expect(floorPowerOfTwo(u32, 64) == 64); |
| 702 | testing.expect(floorPowerOfTwo(u32, 65) == 64); |
| 703 | testing.expect(floorPowerOfTwo(u4, 7) == 4); |
| 704 | testing.expect(floorPowerOfTwo(u4, 8) == 8); |
| 705 | testing.expect(floorPowerOfTwo(u4, 9) == 8); |
| 706 | } |
| 707 | |
| 708 | /// Returns the next power of two (if the value is not already a power of two). |
| 709 | /// Only unsigned integers can be used. Zero is not an allowed input. |
| 710 | /// Result is a type with 1 more bit than the input type. |
| 711 | pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T.bit_count + 1) { |
| 712 | comptime assert(@typeId(T) == builtin.TypeId.Int); |
| 713 | comptime assert(!T.is_signed); |
| 714 | assert(value != 0); |
| 715 | comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1); |
| 716 | comptime const shiftType = std.math.Log2Int(promotedType); |
| 717 | return promotedType(1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1)); |
| 718 | } |
| 719 | |
| 720 | /// Returns the next power of two (if the value is not already a power of two). |
| 721 | /// Only unsigned integers can be used. Zero is not an allowed input. |
| 722 | /// If the value doesn't fit, returns an error. |
| 723 | pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) { |
| 724 | comptime assert(@typeId(T) == builtin.TypeId.Int); |
| 725 | comptime assert(!T.is_signed); |
| 726 | comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1); |
| 727 | comptime const overflowBit = promotedType(1) << T.bit_count; |
| 728 | var x = ceilPowerOfTwoPromote(T, value); |
| 729 | if (overflowBit & x != 0) { |
| 730 | return error.Overflow; |
| 731 | } |
| 732 | return @intCast(T, x); |
| 733 | } |
| 734 | |
| 735 | test "math.ceilPowerOfTwoPromote" { |
| 736 | testCeilPowerOfTwoPromote(); |
| 737 | comptime testCeilPowerOfTwoPromote(); |
| 738 | } |
| 739 | |
| 740 | fn testCeilPowerOfTwoPromote() void { |
| 741 | testing.expectEqual(u33(1), ceilPowerOfTwoPromote(u32, 1)); |
| 742 | testing.expectEqual(u33(2), ceilPowerOfTwoPromote(u32, 2)); |
| 743 | testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 63)); |
| 744 | testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 64)); |
| 745 | testing.expectEqual(u33(128), ceilPowerOfTwoPromote(u32, 65)); |
| 746 | testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 7)); |
| 747 | testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 8)); |
| 748 | testing.expectEqual(u6(16), ceilPowerOfTwoPromote(u5, 9)); |
| 749 | testing.expectEqual(u5(16), ceilPowerOfTwoPromote(u4, 9)); |
| 750 | } |
| 751 | |
| 752 | test "math.ceilPowerOfTwo" { |
| 753 | try testCeilPowerOfTwo(); |
| 754 | comptime try testCeilPowerOfTwo(); |
| 755 | } |
| 756 | |
| 757 | fn testCeilPowerOfTwo() !void { |
| 758 | testing.expectEqual(u32(1), try ceilPowerOfTwo(u32, 1)); |
| 759 | testing.expectEqual(u32(2), try ceilPowerOfTwo(u32, 2)); |
| 760 | testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 63)); |
| 761 | testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 64)); |
| 762 | testing.expectEqual(u32(128), try ceilPowerOfTwo(u32, 65)); |
| 763 | testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 7)); |
| 764 | testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 8)); |
| 765 | testing.expectEqual(u5(16), try ceilPowerOfTwo(u5, 9)); |
| 766 | testing.expectError(error.Overflow, ceilPowerOfTwo(u4, 9)); |
| 767 | } |
| 768 | |
| 699 | 769 | pub fn log2_int(comptime T: type, x: T) Log2Int(T) { |
| 700 | 770 | assert(x != 0); |
| 701 | 771 | return @intCast(Log2Int(T), T.bit_count - 1 - @clz(T, x)); |
| ... | ... | @@ -722,15 +792,6 @@ test "std.math.log2_int_ceil" { |
| 722 | 792 | testing.expect(log2_int_ceil(u32, 10) == 4); |
| 723 | 793 | } |
| 724 | 794 | |
| 725 | | fn testFloorPowerOfTwo() void { |
| 726 | | testing.expect(floorPowerOfTwo(u32, 63) == 32); |
| 727 | | testing.expect(floorPowerOfTwo(u32, 64) == 64); |
| 728 | | testing.expect(floorPowerOfTwo(u32, 65) == 64); |
| 729 | | testing.expect(floorPowerOfTwo(u4, 7) == 4); |
| 730 | | testing.expect(floorPowerOfTwo(u4, 8) == 8); |
| 731 | | testing.expect(floorPowerOfTwo(u4, 9) == 8); |
| 732 | | } |
| 733 | | |
| 734 | 795 | pub fn lossyCast(comptime T: type, value: var) T { |
| 735 | 796 | switch (@typeInfo(@typeOf(value))) { |
| 736 | 797 | builtin.TypeId.Int => return @intToFloat(T, value), |