mirror of
https://github.com/ziglang/zig.git
synced 2025-12-12 17:23:09 +00:00
fix #17142, wrong comptime log_int computation
This commit is contained in:
parent
d55d1e32b6
commit
c5d359e4cd
@ -672,6 +672,7 @@ test "rotl" {
|
|||||||
/// - 1. Suitable for 0-based bit indices of T.
|
/// - 1. Suitable for 0-based bit indices of T.
|
||||||
pub fn Log2Int(comptime T: type) type {
|
pub fn Log2Int(comptime T: type) type {
|
||||||
// comptime ceil log2
|
// comptime ceil log2
|
||||||
|
if (T == comptime_int) return comptime_int;
|
||||||
comptime var count = 0;
|
comptime var count = 0;
|
||||||
comptime var s = @typeInfo(T).Int.bits - 1;
|
comptime var s = @typeInfo(T).Int.bits - 1;
|
||||||
inline while (s != 0) : (s >>= 1) {
|
inline while (s != 0) : (s >>= 1) {
|
||||||
@ -684,6 +685,7 @@ pub fn Log2Int(comptime T: type) type {
|
|||||||
/// Returns an unsigned int type that can hold the number of bits in T.
|
/// Returns an unsigned int type that can hold the number of bits in T.
|
||||||
pub fn Log2IntCeil(comptime T: type) type {
|
pub fn Log2IntCeil(comptime T: type) type {
|
||||||
// comptime ceil log2
|
// comptime ceil log2
|
||||||
|
if (T == comptime_int) return comptime_int;
|
||||||
comptime var count = 0;
|
comptime var count = 0;
|
||||||
comptime var s = @typeInfo(T).Int.bits;
|
comptime var s = @typeInfo(T).Int.bits;
|
||||||
inline while (s != 0) : (s >>= 1) {
|
inline while (s != 0) : (s >>= 1) {
|
||||||
|
|||||||
@ -24,11 +24,8 @@ pub fn log(comptime T: type, base: T, x: T) T {
|
|||||||
return @as(comptime_float, @log(@as(f64, x)) / @log(float_base));
|
return @as(comptime_float, @log(@as(f64, x)) / @log(float_base));
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: implement integer log without using float math.
|
|
||||||
// The present implementation is incorrect, for example
|
|
||||||
// `log(comptime_int, 9, 59049)` should return `5` and not `4`.
|
|
||||||
.ComptimeInt => {
|
.ComptimeInt => {
|
||||||
return @as(comptime_int, @floor(@log(@as(f64, x)) / @log(float_base)));
|
return @as(comptime_int, math.log_int(comptime_int, base, x));
|
||||||
},
|
},
|
||||||
|
|
||||||
.Int => |IntType| switch (IntType.signedness) {
|
.Int => |IntType| switch (IntType.signedness) {
|
||||||
|
|||||||
@ -7,10 +7,15 @@ const Log2Int = math.Log2Int;
|
|||||||
/// Returns the logarithm of `x` for the provided `base`, rounding down to the nearest integer.
|
/// Returns the logarithm of `x` for the provided `base`, rounding down to the nearest integer.
|
||||||
/// Asserts that `base > 1` and `x > 0`.
|
/// Asserts that `base > 1` and `x > 0`.
|
||||||
pub fn log_int(comptime T: type, base: T, x: T) Log2Int(T) {
|
pub fn log_int(comptime T: type, base: T, x: T) Log2Int(T) {
|
||||||
if (@typeInfo(T) != .Int or @typeInfo(T).Int.signedness != .unsigned)
|
const valid = switch (@typeInfo(T)) {
|
||||||
@compileError("log_int requires an unsigned integer, found " ++ @typeName(T));
|
.ComptimeInt => true,
|
||||||
|
.Int => |IntType| IntType.signedness == .unsigned,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
if (!valid) @compileError("log_int requires an unsigned integer, found " ++ @typeName(T));
|
||||||
|
|
||||||
assert(base > 1 and x > 0);
|
assert(base > 1 and x > 0);
|
||||||
|
if (base == 2) return math.log2_int(T, x);
|
||||||
|
|
||||||
// Let's denote by [y] the integer part of y.
|
// Let's denote by [y] the integer part of y.
|
||||||
|
|
||||||
@ -112,3 +117,12 @@ test "math.log_int vs math.log10" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "math.log_int at comptime" {
|
||||||
|
const x = 59049; // 9 ** 5;
|
||||||
|
comptime {
|
||||||
|
if (math.log_int(comptime_int, 9, x) != 5) {
|
||||||
|
@compileError("log(9, 59049) should be 5");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user