| ... | @@ -17,12 +17,20 @@ pub fn log2(x: anytype) @TypeOf(x) { | ... | @@ -17,12 +17,20 @@ pub fn log2(x: anytype) @TypeOf(x) { |
| 17 | }, | 17 | }, |
| 18 | .Float => return @log2(x), | 18 | .Float => return @log2(x), |
| 19 | .ComptimeInt => comptime { | 19 | .ComptimeInt => comptime { |
| 20 | var result = 0; | | |
| 21 | var x_shifted = x; | 20 | var x_shifted = x; |
| 22 | while (b: { | 21 | // First, calculate floorPowerOfTwo(x) |
| 23 | x_shifted >>= 1; | 22 | var shift_amt = 1; |
| 24 | break :b x_shifted != 0; | 23 | while (x_shifted >> (shift_amt << 1) != 0) shift_amt <<= 1; |
| 25 | }) : (result += 1) {} | 24 | |
| | 25 | // Answer is in the range [shift_amt, 2 * shift_amt - 1] |
| | 26 | // We can find it in O(log(N)) using binary search. |
| | 27 | var result = 0; |
| | 28 | while (shift_amt != 0) : (shift_amt >>= 1) { |
| | 29 | if (x_shifted >> shift_amt != 0) { |
| | 30 | x_shifted >>= shift_amt; |
| | 31 | result += shift_amt; |
| | 32 | } |
| | 33 | } |
| 26 | return result; | 34 | return result; |
| 27 | }, | 35 | }, |
| 28 | .Int => |IntType| switch (IntType.signedness) { | 36 | .Int => |IntType| switch (IntType.signedness) { |
| ... | @@ -36,4 +44,10 @@ pub fn log2(x: anytype) @TypeOf(x) { | ... | @@ -36,4 +44,10 @@ pub fn log2(x: anytype) @TypeOf(x) { |
| 36 | test "log2" { | 44 | test "log2" { |
| 37 | try expect(log2(@as(f32, 0.2)) == @log2(0.2)); | 45 | try expect(log2(@as(f32, 0.2)) == @log2(0.2)); |
| 38 | try expect(log2(@as(f64, 0.2)) == @log2(0.2)); | 46 | try expect(log2(@as(f64, 0.2)) == @log2(0.2)); |
| | 47 | comptime { |
| | 48 | try expect(log2(1) == 0); |
| | 49 | try expect(log2(15) == 3); |
| | 50 | try expect(log2(16) == 4); |
| | 51 | try expect(log2(1 << 4073) == 4073); |
| | 52 | } |
| 39 | } | 53 | } |