aboutsummaryrefslogtreecommitdiff
path: root/std/math/log2.zig
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-08-19 01:32:15 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-08-19 01:43:43 -0400
commit987768778a67538299f84a6ab7ff0ca65f69d2ac (patch)
tree2e7551d76bf9a3e6d242a961eacf7c81aab6025f /std/math/log2.zig
parent558ece8f6f1889bc4773432c16cdf96a54ec1431 (diff)
downloadzig-987768778a67538299f84a6ab7ff0ca65f69d2ac.tar.gz
zig-987768778a67538299f84a6ab7ff0ca65f69d2ac.zip
bit shifting safety
* add u3, u4, u5, u6, u7 and i3, i4, i5, i6, i7 * shift operations shift amount parameter type is integer with log2 bit width of other param - This enforces not violating undefined behavior on shift amount >= bit width with the type system * clean up math.log, math.ln, math.log2, math.log10 closes #403
Diffstat (limited to 'std/math/log2.zig')
-rw-r--r--std/math/log2.zig39
1 files changed, 29 insertions, 10 deletions
diff --git a/std/math/log2.zig b/std/math/log2.zig
index 9468abdd4b..fecc9e59e1 100644
--- a/std/math/log2.zig
+++ b/std/math/log2.zig
@@ -7,20 +7,41 @@
const math = @import("index.zig");
const assert = @import("../debug.zig").assert;
+const builtin = @import("builtin");
+const TypeId = builtin.TypeId;
// TODO issue #393
pub const log2 = log2_workaround;
-pub fn log2_workaround(x: var) -> @typeOf(x) {
+fn log2_workaround(x: var) -> @typeOf(x) {
const T = @typeOf(x);
- switch (T) {
- f32 => @inlineCall(log2_32, x),
- f64 => @inlineCall(log2_64, x),
+ switch (@typeId(T)) {
+ TypeId.FloatLiteral => {
+ return @typeOf(1.0)(log2_64(x))
+ },
+ TypeId.Float => {
+ return switch (T) {
+ f32 => log2_32(x),
+ f64 => log2_64(x),
+ else => @compileError("log2 not implemented for " ++ @typeName(T)),
+ };
+ },
+ TypeId.IntLiteral => {
+ return @typeOf(1)(log2_int(u128, x))
+ },
+ TypeId.Int => {
+ return log2_int(T, x);
+ },
else => @compileError("log2 not implemented for " ++ @typeName(T)),
}
}
-fn log2_32(x_: f32) -> f32 {
+pub fn log2_int(comptime T: type, x: T) -> T {
+ assert(x != 0);
+ return T.bit_count - 1 - T(@clz(x));
+}
+
+pub fn log2_32(x_: f32) -> f32 {
const ivln2hi: f32 = 1.4428710938e+00;
const ivln2lo: f32 = -1.7605285393e-04;
const Lg1: f32 = 0xaaaaaa.0p-24;
@@ -76,7 +97,7 @@ fn log2_32(x_: f32) -> f32 {
(lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k)
}
-fn log2_64(x_: f64) -> f64 {
+pub fn log2_64(x_: f64) -> f64 {
const ivln2hi: f64 = 1.44269504072144627571e+00;
const ivln2lo: f64 = 1.67517131648865118353e-10;
const Lg1: f64 = 6.666666666666735130e-01;
@@ -106,11 +127,9 @@ fn log2_64(x_: f64) -> f64 {
k -= 54;
x *= 0x1.0p54;
hx = u32(@bitCast(u64, x) >> 32);
- }
- else if (hx >= 0x7FF00000) {
+ } else if (hx >= 0x7FF00000) {
return x;
- }
- else if (hx == 0x3FF00000 and ix << 32 == 0) {
+ } else if (hx == 0x3FF00000 and ix << 32 == 0) {
return 0;
}