| author | |
| committer | |
| log | c5d359e4cdcc6090f0ff1803adb929247027e7cb |
| tree | 637055ee759a05603fad17d3cced1c1fdb84e0d7 |
| parent | d55d1e32b65dd829cec17b5c5d65db10608d097c |
3 files changed, 19 insertions(+), 6 deletions(-)
lib/std/math.zig+2| ... | @@ -672,6 +672,7 @@ test "rotl" { | ... | @@ -672,6 +672,7 @@ test "rotl" { |
| 672 | /// - 1. Suitable for 0-based bit indices of T. | 672 | /// - 1. Suitable for 0-based bit indices of T. |
| 673 | pub fn Log2Int(comptime T: type) type { | 673 | pub fn Log2Int(comptime T: type) type { |
| 674 | // comptime ceil log2 | 674 | // comptime ceil log2 |
| 675 | if (T == comptime_int) return comptime_int; | ||
| 675 | comptime var count = 0; | 676 | comptime var count = 0; |
| 676 | comptime var s = @typeInfo(T).Int.bits - 1; | 677 | comptime var s = @typeInfo(T).Int.bits - 1; |
| 677 | inline while (s != 0) : (s >>= 1) { | 678 | inline while (s != 0) : (s >>= 1) { |
| ... | @@ -684,6 +685,7 @@ pub fn Log2Int(comptime T: type) type { | ... | @@ -684,6 +685,7 @@ pub fn Log2Int(comptime T: type) type { |
| 684 | /// Returns an unsigned int type that can hold the number of bits in T. | 685 | /// Returns an unsigned int type that can hold the number of bits in T. |
| 685 | pub fn Log2IntCeil(comptime T: type) type { | 686 | pub fn Log2IntCeil(comptime T: type) type { |
| 686 | // comptime ceil log2 | 687 | // comptime ceil log2 |
| 688 | if (T == comptime_int) return comptime_int; | ||
| 687 | comptime var count = 0; | 689 | comptime var count = 0; |
| 688 | comptime var s = @typeInfo(T).Int.bits; | 690 | comptime var s = @typeInfo(T).Int.bits; |
| 689 | inline while (s != 0) : (s >>= 1) { | 691 | inline while (s != 0) : (s >>= 1) { |
lib/std/math/log.zig+1-4| ... | @@ -24,11 +24,8 @@ pub fn log(comptime T: type, base: T, x: T) T { | ... | @@ -24,11 +24,8 @@ pub fn log(comptime T: type, base: T, x: T) T { |
| 24 | return @as(comptime_float, @log(@as(f64, x)) / @log(float_base)); | 24 | return @as(comptime_float, @log(@as(f64, x)) / @log(float_base)); |
| 25 | }, | 25 | }, |
| 26 | 26 | ||
| 27 | // TODO: implement integer log without using float math. | ||
| 28 | // The present implementation is incorrect, for example | ||
| 29 | // `log(comptime_int, 9, 59049)` should return `5` and not `4`. | ||
| 30 | .ComptimeInt => { | 27 | .ComptimeInt => { |
| 31 | return @as(comptime_int, @floor(@log(@as(f64, x)) / @log(float_base))); | 28 | return @as(comptime_int, math.log_int(comptime_int, base, x)); |
| 32 | }, | 29 | }, |
| 33 | 30 | ||
| 34 | .Int => |IntType| switch (IntType.signedness) { | 31 | .Int => |IntType| switch (IntType.signedness) { |
lib/std/math/log_int.zig+16-2| ... | @@ -7,10 +7,15 @@ const Log2Int = math.Log2Int; | ... | @@ -7,10 +7,15 @@ const Log2Int = math.Log2Int; |
| 7 | /// Returns the logarithm of `x` for the provided `base`, rounding down to the nearest integer. | 7 | /// Returns the logarithm of `x` for the provided `base`, rounding down to the nearest integer. |
| 8 | /// Asserts that `base > 1` and `x > 0`. | 8 | /// Asserts that `base > 1` and `x > 0`. |
| 9 | pub fn log_int(comptime T: type, base: T, x: T) Log2Int(T) { | 9 | pub fn log_int(comptime T: type, base: T, x: T) Log2Int(T) { |
| 10 | if (@typeInfo(T) != .Int or @typeInfo(T).Int.signedness != .unsigned) | 10 | const valid = switch (@typeInfo(T)) { |
| 11 | @compileError("log_int requires an unsigned integer, found " ++ @typeName(T)); | 11 | .ComptimeInt => true, |
| 12 | .Int => |IntType| IntType.signedness == .unsigned, | ||
| 13 | else => false, | ||
| 14 | }; | ||
| 15 | if (!valid) @compileError("log_int requires an unsigned integer, found " ++ @typeName(T)); | ||
| 12 | 16 | ||
| 13 | assert(base > 1 and x > 0); | 17 | assert(base > 1 and x > 0); |
| 18 | if (base == 2) return math.log2_int(T, x); | ||
| 14 | 19 | ||
| 15 | // Let's denote by [y] the integer part of y. | 20 | // Let's denote by [y] the integer part of y. |
| 16 | 21 | ||
| ... | @@ -112,3 +117,12 @@ test "math.log_int vs math.log10" { | ... | @@ -112,3 +117,12 @@ test "math.log_int vs math.log10" { |
| 112 | } | 117 | } |
| 113 | } | 118 | } |
| 114 | } | 119 | } |
| 120 | |||
| 121 | test "math.log_int at comptime" { | ||
| 122 | const x = 59049; // 9 ** 5; | ||
| 123 | comptime { | ||
| 124 | if (math.log_int(comptime_int, 9, x) != 5) { | ||
| 125 | @compileError("log(9, 59049) should be 5"); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | } |