| author | |
| committer | |
| log | c9fc8bd802f5ed52c4cc78b93f18fc5dc9b6bb7f |
| tree | 8ddb992d7c1b4ede1b6a99e32fad16c1a476e0c1 |
| parent | 799c69910172a7248ab9db366e6e3a6556e7d626 |
See #393 for details46 files changed, 474 insertions(+), 841 deletions(-)
src/codegen.cpp+1| ... | ... | @@ -438,6 +438,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 438 | 438 | } |
| 439 | 439 | |
| 440 | 440 | addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind"); |
| 441 | addLLVMFnAttr(fn_table_entry->llvm_value, "nobuiltin"); | |
| 441 | 442 | if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) { |
| 442 | 443 | ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true"); |
| 443 | 444 | ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr); |
std/math/acos.zig+9-6| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn acos(x: var) -> @typeOf(x) { | |
| 4 | pub const acos = acos_workaround; | |
| 5 | ||
| 6 | // TODO issue #393 | |
| 7 | pub fn acos_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(acos32, x), |
| ... | ... | @@ -137,12 +140,12 @@ fn acos64(x: f64) -> f64 { |
| 137 | 140 | 2 * (df + w) |
| 138 | 141 | } |
| 139 | 142 | |
| 140 | test "acos" { | |
| 141 | assert(acos(f32(0.0)) == acos32(0.0)); | |
| 142 | assert(acos(f64(0.0)) == acos64(0.0)); | |
| 143 | test "math.acos" { | |
| 144 | assert(acos_workaround(f32(0.0)) == acos32(0.0)); | |
| 145 | assert(acos_workaround(f64(0.0)) == acos64(0.0)); | |
| 143 | 146 | } |
| 144 | 147 | |
| 145 | test "acos32" { | |
| 148 | test "math.acos32" { | |
| 146 | 149 | const epsilon = 0.000001; |
| 147 | 150 | |
| 148 | 151 | assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon)); |
| ... | ... | @@ -153,7 +156,7 @@ test "acos32" { |
| 153 | 156 | assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon)); |
| 154 | 157 | } |
| 155 | 158 | |
| 156 | test "acos64" { | |
| 159 | test "math.acos64" { | |
| 157 | 160 | const epsilon = 0.000001; |
| 158 | 161 | |
| 159 | 162 | assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon)); |
std/math/acosh.zig+21-18| ... | ... | @@ -1,17 +1,20 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn acosh(x: var) -> @typeOf(x) { | |
| 4 | pub const acosh = acosh_workaround; | |
| 5 | ||
| 6 | // TODO issue #393 | |
| 7 | pub fn acosh_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(acoshf, x), | |
| 8 | f64 => @inlineCall(acoshd, x), | |
| 10 | f32 => @inlineCall(acosh32, x), | |
| 11 | f64 => @inlineCall(acosh64, x), | |
| 9 | 12 | else => @compileError("acosh not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | 16 | // acosh(x) = log(x + sqrt(x * x - 1)) |
| 14 | fn acoshf(x: f32) -> f32 { | |
| 17 | fn acosh32(x: f32) -> f32 { | |
| 15 | 18 | const u = @bitCast(u32, x); |
| 16 | 19 | const i = u & 0x7FFFFFFF; |
| 17 | 20 | |
| ... | ... | @@ -29,7 +32,7 @@ fn acoshf(x: f32) -> f32 { |
| 29 | 32 | } |
| 30 | 33 | } |
| 31 | 34 | |
| 32 | fn acoshd(x: f64) -> f64 { | |
| 35 | fn acosh64(x: f64) -> f64 { | |
| 33 | 36 | const u = @bitCast(u64, x); |
| 34 | 37 | const e = (u >> 52) & 0x7FF; |
| 35 | 38 | |
| ... | ... | @@ -47,25 +50,25 @@ fn acoshd(x: f64) -> f64 { |
| 47 | 50 | } |
| 48 | 51 | } |
| 49 | 52 | |
| 50 | test "acosh" { | |
| 51 | assert(acosh(f32(1.5)) == acoshf(1.5)); | |
| 52 | assert(acosh(f64(1.5)) == acoshd(1.5)); | |
| 53 | test "math.acosh" { | |
| 54 | assert(acosh_workaround(f32(1.5)) == acosh32(1.5)); | |
| 55 | assert(acosh_workaround(f64(1.5)) == acosh64(1.5)); | |
| 53 | 56 | } |
| 54 | 57 | |
| 55 | test "acoshf" { | |
| 58 | test "math.acosh32" { | |
| 56 | 59 | const epsilon = 0.000001; |
| 57 | 60 | |
| 58 | assert(math.approxEq(f32, acoshf(1.5), 0.962424, epsilon)); | |
| 59 | assert(math.approxEq(f32, acoshf(37.45), 4.315976, epsilon)); | |
| 60 | assert(math.approxEq(f32, acoshf(89.123), 5.183133, epsilon)); | |
| 61 | assert(math.approxEq(f32, acoshf(123123.234375), 12.414088, epsilon)); | |
| 61 | assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon)); | |
| 62 | assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon)); | |
| 63 | assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon)); | |
| 64 | assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon)); | |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | test "acoshd" { | |
| 67 | test "math.acosh64" { | |
| 65 | 68 | const epsilon = 0.000001; |
| 66 | 69 | |
| 67 | assert(math.approxEq(f64, acoshd(1.5), 0.962424, epsilon)); | |
| 68 | assert(math.approxEq(f64, acoshd(37.45), 4.315976, epsilon)); | |
| 69 | assert(math.approxEq(f64, acoshd(89.123), 5.183133, epsilon)); | |
| 70 | assert(math.approxEq(f64, acoshd(123123.234375), 12.414088, epsilon)); | |
| 70 | assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon)); | |
| 71 | assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon)); | |
| 72 | assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon)); | |
| 73 | assert(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon)); | |
| 71 | 74 | } |
std/math/asin.zig+9-6| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn asin(x: var) -> @typeOf(x) { | |
| 4 | pub const asin = asin_workaround; | |
| 5 | ||
| 6 | // TODO issue #393 | |
| 7 | pub fn asin_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(asin32, x), |
| ... | ... | @@ -129,12 +132,12 @@ fn asin64(x: f64) -> f64 { |
| 129 | 132 | } |
| 130 | 133 | } |
| 131 | 134 | |
| 132 | test "asin" { | |
| 133 | assert(asin(f32(0.0)) == asin32(0.0)); | |
| 134 | assert(asin(f64(0.0)) == asin64(0.0)); | |
| 135 | test "math.asin" { | |
| 136 | assert(asin_workaround(f32(0.0)) == asin32(0.0)); | |
| 137 | assert(asin_workaround(f64(0.0)) == asin64(0.0)); | |
| 135 | 138 | } |
| 136 | 139 | |
| 137 | test "asin32" { | |
| 140 | test "math.asin32" { | |
| 138 | 141 | const epsilon = 0.000001; |
| 139 | 142 | |
| 140 | 143 | assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon)); |
| ... | ... | @@ -145,7 +148,7 @@ test "asin32" { |
| 145 | 148 | assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon)); |
| 146 | 149 | } |
| 147 | 150 | |
| 148 | test "asin64" { | |
| 151 | test "math.asin64" { | |
| 149 | 152 | const epsilon = 0.000001; |
| 150 | 153 | |
| 151 | 154 | assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon)); |
std/math/asinh.zig+27-24| ... | ... | @@ -1,17 +1,20 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn asinh(x: var) -> @typeOf(x) { | |
| 4 | pub const asinh = asinh_workaround; | |
| 5 | ||
| 6 | // TODO issue #393 | |
| 7 | pub fn asinh_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(asinhf, x), | |
| 8 | f64 => @inlineCall(asinhd, x), | |
| 10 | f32 => @inlineCall(asinh32, x), | |
| 11 | f64 => @inlineCall(asinh64, x), | |
| 9 | 12 | else => @compileError("asinh not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | 16 | // asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5) |
| 14 | fn asinhf(x: f32) -> f32 { | |
| 17 | fn asinh32(x: f32) -> f32 { | |
| 15 | 18 | const u = @bitCast(u32, x); |
| 16 | 19 | const i = u & 0x7FFFFFFF; |
| 17 | 20 | const s = i >> 31; |
| ... | ... | @@ -38,7 +41,7 @@ fn asinhf(x: f32) -> f32 { |
| 38 | 41 | if (s != 0) -rx else rx |
| 39 | 42 | } |
| 40 | 43 | |
| 41 | fn asinhd(x: f64) -> f64 { | |
| 44 | fn asinh64(x: f64) -> f64 { | |
| 42 | 45 | const u = @bitCast(u64, x); |
| 43 | 46 | const e = (u >> 52) & 0x7FF; |
| 44 | 47 | const s = u >> 63; |
| ... | ... | @@ -65,31 +68,31 @@ fn asinhd(x: f64) -> f64 { |
| 65 | 68 | if (s != 0) -rx else rx |
| 66 | 69 | } |
| 67 | 70 | |
| 68 | test "asinh" { | |
| 69 | assert(asinh(f32(0.0)) == asinhf(0.0)); | |
| 70 | assert(asinh(f64(0.0)) == asinhd(0.0)); | |
| 71 | test "math.asinh" { | |
| 72 | assert(asinh_workaround(f32(0.0)) == asinh32(0.0)); | |
| 73 | assert(asinh_workaround(f64(0.0)) == asinh64(0.0)); | |
| 71 | 74 | } |
| 72 | 75 | |
| 73 | test "asinhf" { | |
| 76 | test "math.asinh32" { | |
| 74 | 77 | const epsilon = 0.000001; |
| 75 | 78 | |
| 76 | assert(math.approxEq(f32, asinhf(0.0), 0.0, epsilon)); | |
| 77 | assert(math.approxEq(f32, asinhf(0.2), 0.198690, epsilon)); | |
| 78 | assert(math.approxEq(f32, asinhf(0.8923), 0.803133, epsilon)); | |
| 79 | assert(math.approxEq(f32, asinhf(1.5), 1.194763, epsilon)); | |
| 80 | assert(math.approxEq(f32, asinhf(37.45), 4.316332, epsilon)); | |
| 81 | assert(math.approxEq(f32, asinhf(89.123), 5.183196, epsilon)); | |
| 82 | assert(math.approxEq(f32, asinhf(123123.234375), 12.414088, epsilon)); | |
| 79 | assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon)); | |
| 80 | assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon)); | |
| 81 | assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon)); | |
| 82 | assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon)); | |
| 83 | assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon)); | |
| 84 | assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon)); | |
| 85 | assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon)); | |
| 83 | 86 | } |
| 84 | 87 | |
| 85 | test "asinhd" { | |
| 88 | test "math.asinh64" { | |
| 86 | 89 | const epsilon = 0.000001; |
| 87 | 90 | |
| 88 | assert(math.approxEq(f64, asinhd(0.0), 0.0, epsilon)); | |
| 89 | assert(math.approxEq(f64, asinhd(0.2), 0.198690, epsilon)); | |
| 90 | assert(math.approxEq(f64, asinhd(0.8923), 0.803133, epsilon)); | |
| 91 | assert(math.approxEq(f64, asinhd(1.5), 1.194763, epsilon)); | |
| 92 | assert(math.approxEq(f64, asinhd(37.45), 4.316332, epsilon)); | |
| 93 | assert(math.approxEq(f64, asinhd(89.123), 5.183196, epsilon)); | |
| 94 | assert(math.approxEq(f64, asinhd(123123.234375), 12.414088, epsilon)); | |
| 91 | assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon)); | |
| 92 | assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon)); | |
| 93 | assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon)); | |
| 94 | assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon)); | |
| 95 | assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon)); | |
| 96 | assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon)); | |
| 97 | assert(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon)); | |
| 95 | 98 | } |
std/math/atan.zig+9-6| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn atan(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const atan = atan_workaround; | |
| 6 | ||
| 7 | pub fn atan_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(atan32, x), |
| ... | ... | @@ -201,12 +204,12 @@ fn atan64(x_: f64) -> f64 { |
| 201 | 204 | } |
| 202 | 205 | } |
| 203 | 206 | |
| 204 | test "atan" { | |
| 205 | assert(atan(f32(0.2)) == atan32(0.2)); | |
| 206 | assert(atan(f64(0.2)) == atan64(0.2)); | |
| 207 | test "math.atan" { | |
| 208 | assert(atan_workaround(f32(0.2)) == atan32(0.2)); | |
| 209 | assert(atan_workaround(f64(0.2)) == atan64(0.2)); | |
| 207 | 210 | } |
| 208 | 211 | |
| 209 | test "atan32" { | |
| 212 | test "math.atan32" { | |
| 210 | 213 | const epsilon = 0.000001; |
| 211 | 214 | |
| 212 | 215 | assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon)); |
| ... | ... | @@ -216,7 +219,7 @@ test "atan32" { |
| 216 | 219 | assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon)); |
| 217 | 220 | } |
| 218 | 221 | |
| 219 | test "atan64" { | |
| 222 | test "math.atan64" { | |
| 220 | 223 | const epsilon = 0.000001; |
| 221 | 224 | |
| 222 | 225 | assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon)); |
std/math/atan2.zig+27-24| ... | ... | @@ -1,15 +1,18 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn atan2(comptime T: type, x: T, y: T) -> T { | |
| 4 | pub const atan2 = atan2_workaround; | |
| 5 | ||
| 6 | // TODO issue #393 | |
| 7 | pub fn atan2_workaround(comptime T: type, x: T, y: T) -> T { | |
| 5 | 8 | switch (T) { |
| 6 | f32 => @inlineCall(atan2f, x, y), | |
| 7 | f64 => @inlineCall(atan2d, x, y), | |
| 9 | f32 => @inlineCall(atan2_32, x, y), | |
| 10 | f64 => @inlineCall(atan2_64, x, y), | |
| 8 | 11 | else => @compileError("atan2 not implemented for " ++ @typeName(T)), |
| 9 | 12 | } |
| 10 | 13 | } |
| 11 | 14 | |
| 12 | fn atan2f(y: f32, x: f32) -> f32 { | |
| 15 | fn atan2_32(y: f32, x: f32) -> f32 { | |
| 13 | 16 | const pi: f32 = 3.1415927410e+00; |
| 14 | 17 | const pi_lo: f32 = -8.7422776573e-08; |
| 15 | 18 | |
| ... | ... | @@ -94,7 +97,7 @@ fn atan2f(y: f32, x: f32) -> f32 { |
| 94 | 97 | } |
| 95 | 98 | } |
| 96 | 99 | |
| 97 | fn atan2d(y: f64, x: f64) -> f64 { | |
| 100 | fn atan2_64(y: f64, x: f64) -> f64 { | |
| 98 | 101 | const pi: f64 = 3.1415926535897931160E+00; |
| 99 | 102 | const pi_lo: f64 = 1.2246467991473531772E-16; |
| 100 | 103 | |
| ... | ... | @@ -184,31 +187,31 @@ fn atan2d(y: f64, x: f64) -> f64 { |
| 184 | 187 | } |
| 185 | 188 | } |
| 186 | 189 | |
| 187 | test "atan2" { | |
| 188 | assert(atan2(f32, 0.2, 0.21) == atan2f(0.2, 0.21)); | |
| 189 | assert(atan2(f64, 0.2, 0.21) == atan2d(0.2, 0.21)); | |
| 190 | test "math.atan2" { | |
| 191 | assert(atan2_workaround(f32, 0.2, 0.21) == atan2_32(0.2, 0.21)); | |
| 192 | assert(atan2_workaround(f64, 0.2, 0.21) == atan2_64(0.2, 0.21)); | |
| 190 | 193 | } |
| 191 | 194 | |
| 192 | test "atan2f" { | |
| 195 | test "math.atan2_32" { | |
| 193 | 196 | const epsilon = 0.000001; |
| 194 | 197 | |
| 195 | assert(math.approxEq(f32, atan2f(0.0, 0.0), 0.0, epsilon)); | |
| 196 | assert(math.approxEq(f32, atan2f(0.2, 0.2), 0.785398, epsilon)); | |
| 197 | assert(math.approxEq(f32, atan2f(-0.2, 0.2), -0.785398, epsilon)); | |
| 198 | assert(math.approxEq(f32, atan2f(0.2, -0.2), 2.356194, epsilon)); | |
| 199 | assert(math.approxEq(f32, atan2f(-0.2, -0.2), -2.356194, epsilon)); | |
| 200 | assert(math.approxEq(f32, atan2f(0.34, -0.4), 2.437099, epsilon)); | |
| 201 | assert(math.approxEq(f32, atan2f(0.34, 1.243), 0.267001, epsilon)); | |
| 198 | assert(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon)); | |
| 199 | assert(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon)); | |
| 200 | assert(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon)); | |
| 201 | assert(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon)); | |
| 202 | assert(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon)); | |
| 203 | assert(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon)); | |
| 204 | assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon)); | |
| 202 | 205 | } |
| 203 | 206 | |
| 204 | test "atan2d" { | |
| 207 | test "math.atan2_64" { | |
| 205 | 208 | const epsilon = 0.000001; |
| 206 | 209 | |
| 207 | assert(math.approxEq(f64, atan2d(0.0, 0.0), 0.0, epsilon)); | |
| 208 | assert(math.approxEq(f64, atan2d(0.2, 0.2), 0.785398, epsilon)); | |
| 209 | assert(math.approxEq(f64, atan2d(-0.2, 0.2), -0.785398, epsilon)); | |
| 210 | assert(math.approxEq(f64, atan2d(0.2, -0.2), 2.356194, epsilon)); | |
| 211 | assert(math.approxEq(f64, atan2d(-0.2, -0.2), -2.356194, epsilon)); | |
| 212 | assert(math.approxEq(f64, atan2d(0.34, -0.4), 2.437099, epsilon)); | |
| 213 | assert(math.approxEq(f64, atan2d(0.34, 1.243), 0.267001, epsilon)); | |
| 210 | assert(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon)); | |
| 211 | assert(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon)); | |
| 212 | assert(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon)); | |
| 213 | assert(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon)); | |
| 214 | assert(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon)); | |
| 215 | assert(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon)); | |
| 216 | assert(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon)); | |
| 214 | 217 | } |
std/math/atanh.zig+19-16| ... | ... | @@ -1,17 +1,20 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn atanh(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const atanh = atanh_workaround; | |
| 6 | ||
| 7 | pub fn atanh_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(atanhf, x), | |
| 8 | f64 => @inlineCall(atanhd, x), | |
| 10 | f32 => @inlineCall(atanh_32, x), | |
| 11 | f64 => @inlineCall(atanh_64, x), | |
| 9 | 12 | else => @compileError("atanh not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | 16 | // atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5) |
| 14 | fn atanhf(x: f32) -> f32 { | |
| 17 | fn atanh_32(x: f32) -> f32 { | |
| 15 | 18 | const u = @bitCast(u32, x); |
| 16 | 19 | const i = u & 0x7FFFFFFF; |
| 17 | 20 | const s = u >> 31; |
| ... | ... | @@ -37,7 +40,7 @@ fn atanhf(x: f32) -> f32 { |
| 37 | 40 | if (s != 0) -y else y |
| 38 | 41 | } |
| 39 | 42 | |
| 40 | fn atanhd(x: f64) -> f64 { | |
| 43 | fn atanh_64(x: f64) -> f64 { | |
| 41 | 44 | const u = @bitCast(u64, x); |
| 42 | 45 | const e = (u >> 52) & 0x7FF; |
| 43 | 46 | const s = u >> 63; |
| ... | ... | @@ -63,23 +66,23 @@ fn atanhd(x: f64) -> f64 { |
| 63 | 66 | if (s != 0) -y else y |
| 64 | 67 | } |
| 65 | 68 | |
| 66 | test "atanh" { | |
| 67 | assert(atanh(f32(0.0)) == atanhf(0.0)); | |
| 68 | assert(atanh(f64(0.0)) == atanhd(0.0)); | |
| 69 | test "math.atanh" { | |
| 70 | assert(atanh(f32(0.0)) == atanh_32(0.0)); | |
| 71 | assert(atanh(f64(0.0)) == atanh_64(0.0)); | |
| 69 | 72 | } |
| 70 | 73 | |
| 71 | test "atanhf" { | |
| 74 | test "math.atanh_32" { | |
| 72 | 75 | const epsilon = 0.000001; |
| 73 | 76 | |
| 74 | assert(math.approxEq(f32, atanhf(0.0), 0.0, epsilon)); | |
| 75 | assert(math.approxEq(f32, atanhf(0.2), 0.202733, epsilon)); | |
| 76 | assert(math.approxEq(f32, atanhf(0.8923), 1.433099, epsilon)); | |
| 77 | assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon)); | |
| 78 | assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon)); | |
| 79 | assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon)); | |
| 77 | 80 | } |
| 78 | 81 | |
| 79 | test "atanhd" { | |
| 82 | test "math.atanh_64" { | |
| 80 | 83 | const epsilon = 0.000001; |
| 81 | 84 | |
| 82 | assert(math.approxEq(f64, atanhd(0.0), 0.0, epsilon)); | |
| 83 | assert(math.approxEq(f64, atanhd(0.2), 0.202733, epsilon)); | |
| 84 | assert(math.approxEq(f64, atanhd(0.8923), 1.433099, epsilon)); | |
| 85 | assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon)); | |
| 86 | assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon)); | |
| 87 | assert(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon)); | |
| 85 | 88 | } |
std/math/cbrt.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn cbrt(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const cbrt = cbrt_workaround; | |
| 6 | ||
| 7 | pub fn cbrt_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(cbrt32, x), |
| ... | ... | @@ -106,12 +109,12 @@ fn cbrt64(x: f64) -> f64 { |
| 106 | 109 | t + t * q |
| 107 | 110 | } |
| 108 | 111 | |
| 109 | test "cbrt" { | |
| 112 | test "math.cbrt" { | |
| 110 | 113 | assert(cbrt(f32(0.0)) == cbrt32(0.0)); |
| 111 | 114 | assert(cbrt(f64(0.0)) == cbrt64(0.0)); |
| 112 | 115 | } |
| 113 | 116 | |
| 114 | test "cbrt32" { | |
| 117 | test "math.cbrt32" { | |
| 115 | 118 | const epsilon = 0.000001; |
| 116 | 119 | |
| 117 | 120 | assert(cbrt32(0.0) == 0.0); |
| ... | ... | @@ -122,7 +125,7 @@ test "cbrt32" { |
| 122 | 125 | assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon)); |
| 123 | 126 | } |
| 124 | 127 | |
| 125 | test "cbrt64" { | |
| 128 | test "math.cbrt64" { | |
| 126 | 129 | const epsilon = 0.000001; |
| 127 | 130 | |
| 128 | 131 | assert(cbrt64(0.0) == 0.0); |
std/math/ceil.zig+7-4| ... | ... | @@ -2,7 +2,10 @@ const builtin = @import("builtin"); |
| 2 | 2 | const math = @import("index.zig"); |
| 3 | 3 | const assert = @import("../debug.zig").assert; |
| 4 | 4 | |
| 5 | pub fn ceil(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const ceil = ceil_workaround; | |
| 7 | ||
| 8 | pub fn ceil_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | 11 | f32 => @inlineCall(ceil32, x), |
| ... | ... | @@ -71,18 +74,18 @@ fn ceil64(x: f64) -> f64 { |
| 71 | 74 | } |
| 72 | 75 | } |
| 73 | 76 | |
| 74 | test "ceil" { | |
| 77 | test "math.ceil" { | |
| 75 | 78 | assert(ceil(f32(0.0)) == ceil32(0.0)); |
| 76 | 79 | assert(ceil(f64(0.0)) == ceil64(0.0)); |
| 77 | 80 | } |
| 78 | 81 | |
| 79 | test "ceil32" { | |
| 82 | test "math.ceil32" { | |
| 80 | 83 | assert(ceil32(1.3) == 2.0); |
| 81 | 84 | assert(ceil32(-1.3) == -1.0); |
| 82 | 85 | assert(ceil32(0.2) == 1.0); |
| 83 | 86 | } |
| 84 | 87 | |
| 85 | test "ceil64" { | |
| 88 | test "math.ceil64" { | |
| 86 | 89 | assert(ceil64(1.3) == 2.0); |
| 87 | 90 | assert(ceil64(-1.3) == -1.0); |
| 88 | 91 | assert(ceil64(0.2) == 1.0); |
std/math/copysign.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn copysign(comptime T: type, x: T, y: T) -> T { | |
| 4 | // TODO issue #393 | |
| 5 | pub const copysign = copysign_workaround; | |
| 6 | ||
| 7 | pub fn copysign_workaround(comptime T: type, x: T, y: T) -> T { | |
| 5 | 8 | switch (T) { |
| 6 | 9 | f32 => @inlineCall(copysign32, x, y), |
| 7 | 10 | f64 => @inlineCall(copysign64, x, y), |
| ... | ... | @@ -27,19 +30,19 @@ fn copysign64(x: f64, y: f64) -> f64 { |
| 27 | 30 | @bitCast(f64, h1 | h2) |
| 28 | 31 | } |
| 29 | 32 | |
| 30 | test "copysign" { | |
| 33 | test "math.copysign" { | |
| 31 | 34 | assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0)); |
| 32 | 35 | assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0)); |
| 33 | 36 | } |
| 34 | 37 | |
| 35 | test "copysign32" { | |
| 38 | test "math.copysign32" { | |
| 36 | 39 | assert(copysign32(5.0, 1.0) == 5.0); |
| 37 | 40 | assert(copysign32(5.0, -1.0) == -5.0); |
| 38 | 41 | assert(copysign32(-5.0, -1.0) == -5.0); |
| 39 | 42 | assert(copysign32(-5.0, 1.0) == 5.0); |
| 40 | 43 | } |
| 41 | 44 | |
| 42 | test "copysign64" { | |
| 45 | test "math.copysign64" { | |
| 43 | 46 | assert(copysign64(5.0, 1.0) == 5.0); |
| 44 | 47 | assert(copysign64(5.0, -1.0) == -5.0); |
| 45 | 48 | assert(copysign64(-5.0, -1.0) == -5.0); |
std/math/cos.zig+8-4| ... | ... | @@ -1,7 +1,11 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn cos(x: var) -> @typeOf(x) { | |
| 4 | ||
| 5 | // TODO issue #393 | |
| 6 | pub const cos = cos_workaround; | |
| 7 | ||
| 8 | pub fn cos_workaround(x: var) -> @typeOf(x) { | |
| 5 | 9 | const T = @typeOf(x); |
| 6 | 10 | switch (T) { |
| 7 | 11 | f32 => @inlineCall(cos32, x), |
| ... | ... | @@ -133,12 +137,12 @@ fn cos64(x_: f64) -> f64 { |
| 133 | 137 | } |
| 134 | 138 | } |
| 135 | 139 | |
| 136 | test "cos" { | |
| 140 | test "math.cos" { | |
| 137 | 141 | assert(cos(f32(0.0)) == cos32(0.0)); |
| 138 | 142 | assert(cos(f64(0.0)) == cos64(0.0)); |
| 139 | 143 | } |
| 140 | 144 | |
| 141 | test "cos32" { | |
| 145 | test "math.cos32" { | |
| 142 | 146 | const epsilon = 0.000001; |
| 143 | 147 | |
| 144 | 148 | assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); |
| ... | ... | @@ -149,7 +153,7 @@ test "cos32" { |
| 149 | 153 | assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon)); |
| 150 | 154 | } |
| 151 | 155 | |
| 152 | test "cos64" { | |
| 156 | test "math.cos64" { | |
| 153 | 157 | const epsilon = 0.000001; |
| 154 | 158 | |
| 155 | 159 | assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon)); |
std/math/cosh.zig+21-18| ... | ... | @@ -2,11 +2,14 @@ const math = @import("index.zig"); |
| 2 | 2 | const expo2 = @import("_expo2.zig").expo2; |
| 3 | 3 | const assert = @import("../debug.zig").assert; |
| 4 | 4 | |
| 5 | pub fn cosh(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const cosh = cosh_workaround; | |
| 7 | ||
| 8 | pub fn cosh_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | f32 => @inlineCall(coshf, x), | |
| 9 | f64 => @inlineCall(coshd, x), | |
| 11 | f32 => @inlineCall(cosh32, x), | |
| 12 | f64 => @inlineCall(cosh64, x), | |
| 10 | 13 | else => @compileError("cosh not implemented for " ++ @typeName(T)), |
| 11 | 14 | } |
| 12 | 15 | } |
| ... | ... | @@ -14,7 +17,7 @@ pub fn cosh(x: var) -> @typeOf(x) { |
| 14 | 17 | // cosh(x) = (exp(x) + 1 / exp(x)) / 2 |
| 15 | 18 | // = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x) |
| 16 | 19 | // = 1 + (x * x) / 2 + o(x^4) |
| 17 | fn coshf(x: f32) -> f32 { | |
| 20 | fn cosh32(x: f32) -> f32 { | |
| 18 | 21 | const u = @bitCast(u32, x); |
| 19 | 22 | const ux = u & 0x7FFFFFFF; |
| 20 | 23 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -39,7 +42,7 @@ fn coshf(x: f32) -> f32 { |
| 39 | 42 | expo2(ax) |
| 40 | 43 | } |
| 41 | 44 | |
| 42 | fn coshd(x: f64) -> f64 { | |
| 45 | fn cosh64(x: f64) -> f64 { | |
| 43 | 46 | const u = @bitCast(u64, x); |
| 44 | 47 | const w = u32(u >> 32); |
| 45 | 48 | const ax = @bitCast(f64, u & (@maxValue(u64) >> 1)); |
| ... | ... | @@ -67,25 +70,25 @@ fn coshd(x: f64) -> f64 { |
| 67 | 70 | expo2(ax) |
| 68 | 71 | } |
| 69 | 72 | |
| 70 | test "cosh" { | |
| 71 | assert(cosh(f32(1.5)) == coshf(1.5)); | |
| 72 | assert(cosh(f64(1.5)) == coshd(1.5)); | |
| 73 | test "math.cosh" { | |
| 74 | assert(cosh(f32(1.5)) == cosh32(1.5)); | |
| 75 | assert(cosh(f64(1.5)) == cosh64(1.5)); | |
| 73 | 76 | } |
| 74 | 77 | |
| 75 | test "coshf" { | |
| 78 | test "math.cosh32" { | |
| 76 | 79 | const epsilon = 0.000001; |
| 77 | 80 | |
| 78 | assert(math.approxEq(f32, coshf(0.0), 1.0, epsilon)); | |
| 79 | assert(math.approxEq(f32, coshf(0.2), 1.020067, epsilon)); | |
| 80 | assert(math.approxEq(f32, coshf(0.8923), 1.425225, epsilon)); | |
| 81 | assert(math.approxEq(f32, coshf(1.5), 2.352410, epsilon)); | |
| 81 | assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon)); | |
| 82 | assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon)); | |
| 83 | assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon)); | |
| 84 | assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon)); | |
| 82 | 85 | } |
| 83 | 86 | |
| 84 | test "coshd" { | |
| 87 | test "math.cosh64" { | |
| 85 | 88 | const epsilon = 0.000001; |
| 86 | 89 | |
| 87 | assert(math.approxEq(f64, coshd(0.0), 1.0, epsilon)); | |
| 88 | assert(math.approxEq(f64, coshd(0.2), 1.020067, epsilon)); | |
| 89 | assert(math.approxEq(f64, coshd(0.8923), 1.425225, epsilon)); | |
| 90 | assert(math.approxEq(f64, coshd(1.5), 2.352410, epsilon)); | |
| 90 | assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon)); | |
| 91 | assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon)); | |
| 92 | assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon)); | |
| 93 | assert(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon)); | |
| 91 | 94 | } |
std/math/exp.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn exp(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const exp = exp_workaround; | |
| 6 | ||
| 7 | pub fn exp_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(exp32, x), |
| ... | ... | @@ -165,12 +168,12 @@ fn exp64(x_: f64) -> f64 { |
| 165 | 168 | } |
| 166 | 169 | } |
| 167 | 170 | |
| 168 | test "exp" { | |
| 171 | test "math.exp" { | |
| 169 | 172 | assert(exp(f32(0.0)) == exp32(0.0)); |
| 170 | 173 | assert(exp(f64(0.0)) == exp64(0.0)); |
| 171 | 174 | } |
| 172 | 175 | |
| 173 | test "exp32" { | |
| 176 | test "math.exp32" { | |
| 174 | 177 | const epsilon = 0.000001; |
| 175 | 178 | |
| 176 | 179 | assert(exp32(0.0) == 1.0); |
| ... | ... | @@ -180,7 +183,7 @@ test "exp32" { |
| 180 | 183 | assert(math.approxEq(f32, exp32(1.5), 4.481689, epsilon)); |
| 181 | 184 | } |
| 182 | 185 | |
| 183 | test "exp64" { | |
| 186 | test "math.exp64" { | |
| 184 | 187 | const epsilon = 0.000001; |
| 185 | 188 | |
| 186 | 189 | assert(exp64(0.0) == 1.0); |
std/math/exp2.zig+23-20| ... | ... | @@ -1,11 +1,14 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn exp2(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const exp2 = exp2_workaround; | |
| 6 | ||
| 7 | pub fn exp2_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(exp2f, x), | |
| 8 | f64 => @inlineCall(exp2d, x), | |
| 10 | f32 => @inlineCall(exp2_32, x), | |
| 11 | f64 => @inlineCall(exp2_64, x), | |
| 9 | 12 | else => @compileError("exp2 not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| ... | ... | @@ -29,7 +32,7 @@ const exp2ft = []const f64 { |
| 29 | 32 | 0x1.5ab07dd485429p+0, |
| 30 | 33 | }; |
| 31 | 34 | |
| 32 | fn exp2f(x: f32) -> f32 { | |
| 35 | fn exp2_32(x: f32) -> f32 { | |
| 33 | 36 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 34 | 37 | |
| 35 | 38 | const tblsiz = u32(exp2ft.len); |
| ... | ... | @@ -346,7 +349,7 @@ const exp2dt = []f64 { |
| 346 | 349 | 0x1.690f4b19e9471p+0, -0x1.9780p-45, |
| 347 | 350 | }; |
| 348 | 351 | |
| 349 | fn exp2d(x: f64) -> f64 { | |
| 352 | fn exp2_64(x: f64) -> f64 { | |
| 350 | 353 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 351 | 354 | |
| 352 | 355 | const tblsiz = u32(exp2dt.len / 2); |
| ... | ... | @@ -407,27 +410,27 @@ fn exp2d(x: f64) -> f64 { |
| 407 | 410 | math.scalbn(r, ik) |
| 408 | 411 | } |
| 409 | 412 | |
| 410 | test "exp2" { | |
| 411 | assert(exp2(f32(0.8923)) == exp2f(0.8923)); | |
| 412 | assert(exp2(f64(0.8923)) == exp2d(0.8923)); | |
| 413 | test "math.exp2" { | |
| 414 | assert(exp2(f32(0.8923)) == exp2_32(0.8923)); | |
| 415 | assert(exp2(f64(0.8923)) == exp2_64(0.8923)); | |
| 413 | 416 | } |
| 414 | 417 | |
| 415 | test "exp2f" { | |
| 418 | test "math.exp2_32" { | |
| 416 | 419 | const epsilon = 0.000001; |
| 417 | 420 | |
| 418 | assert(exp2f(0.0) == 1.0); | |
| 419 | assert(math.approxEq(f32, exp2f(0.2), 1.148698, epsilon)); | |
| 420 | assert(math.approxEq(f32, exp2f(0.8923), 1.856133, epsilon)); | |
| 421 | assert(math.approxEq(f32, exp2f(1.5), 2.828427, epsilon)); | |
| 422 | assert(math.approxEq(f32, exp2f(37.45), 187747237888, epsilon)); | |
| 421 | assert(exp2_32(0.0) == 1.0); | |
| 422 | assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon)); | |
| 423 | assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon)); | |
| 424 | assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon)); | |
| 425 | assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon)); | |
| 423 | 426 | } |
| 424 | 427 | |
| 425 | test "exp2d" { | |
| 428 | test "math.exp2_64" { | |
| 426 | 429 | const epsilon = 0.000001; |
| 427 | 430 | |
| 428 | assert(exp2d(0.0) == 1.0); | |
| 429 | assert(math.approxEq(f64, exp2d(0.2), 1.148698, epsilon)); | |
| 430 | assert(math.approxEq(f64, exp2d(0.8923), 1.856133, epsilon)); | |
| 431 | assert(math.approxEq(f64, exp2d(1.5), 2.828427, epsilon)); | |
| 432 | // assert(math.approxEq(f64, exp2d(37.45), 18379273786760560.000000, epsilon)); | |
| 431 | assert(exp2_64(0.0) == 1.0); | |
| 432 | assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon)); | |
| 433 | assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon)); | |
| 434 | assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon)); | |
| 435 | // assert(math.approxEq(f64, exp2_64(37.45), 18379273786760560.000000, epsilon)); | |
| 433 | 436 | } |
std/math/expm1.zig+23-20| ... | ... | @@ -1,16 +1,19 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn expm1(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const expm1 = expm1_workaround; | |
| 6 | ||
| 7 | pub fn expm1_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(expm1f, x), | |
| 8 | f64 => @inlineCall(expm1d, x), | |
| 10 | f32 => @inlineCall(expm1_32, x), | |
| 11 | f64 => @inlineCall(expm1_64, x), | |
| 9 | 12 | else => @compileError("exp1m not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | fn expm1f(x_: f32) -> f32 { | |
| 16 | fn expm1_32(x_: f32) -> f32 { | |
| 14 | 17 | const o_threshold: f32 = 8.8721679688e+01; |
| 15 | 18 | const ln2_hi: f32 = 6.9313812256e-01; |
| 16 | 19 | const ln2_lo: f32 = 9.0580006145e-06; |
| ... | ... | @@ -131,7 +134,7 @@ fn expm1f(x_: f32) -> f32 { |
| 131 | 134 | } |
| 132 | 135 | } |
| 133 | 136 | |
| 134 | fn expm1d(x_: f64) -> f64 { | |
| 137 | fn expm1_64(x_: f64) -> f64 { | |
| 135 | 138 | const o_threshold: f64 = 7.09782712893383973096e+02; |
| 136 | 139 | const ln2_hi: f64 = 6.93147180369123816490e-01; |
| 137 | 140 | const ln2_lo: f64 = 1.90821492927058770002e-10; |
| ... | ... | @@ -256,27 +259,27 @@ fn expm1d(x_: f64) -> f64 { |
| 256 | 259 | } |
| 257 | 260 | } |
| 258 | 261 | |
| 259 | test "exp1m" { | |
| 260 | assert(expm1(f32(0.0)) == expm1f(0.0)); | |
| 261 | assert(expm1(f64(0.0)) == expm1d(0.0)); | |
| 262 | test "math.exp1m" { | |
| 263 | assert(expm1(f32(0.0)) == expm1_32(0.0)); | |
| 264 | assert(expm1(f64(0.0)) == expm1_64(0.0)); | |
| 262 | 265 | } |
| 263 | 266 | |
| 264 | test "expm1f" { | |
| 267 | test "math.expm1_32" { | |
| 265 | 268 | const epsilon = 0.000001; |
| 266 | 269 | |
| 267 | assert(expm1f(0.0) == 0.0); | |
| 268 | assert(math.approxEq(f32, expm1f(0.0), 0.0, epsilon)); | |
| 269 | assert(math.approxEq(f32, expm1f(0.2), 0.221403, epsilon)); | |
| 270 | assert(math.approxEq(f32, expm1f(0.8923), 1.440737, epsilon)); | |
| 271 | assert(math.approxEq(f32, expm1f(1.5), 3.481689, epsilon)); | |
| 270 | assert(expm1_32(0.0) == 0.0); | |
| 271 | assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon)); | |
| 272 | assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon)); | |
| 273 | assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon)); | |
| 274 | assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon)); | |
| 272 | 275 | } |
| 273 | 276 | |
| 274 | test "expm1d" { | |
| 277 | test "math.expm1_64" { | |
| 275 | 278 | const epsilon = 0.000001; |
| 276 | 279 | |
| 277 | assert(expm1d(0.0) == 0.0); | |
| 278 | assert(math.approxEq(f64, expm1d(0.0), 0.0, epsilon)); | |
| 279 | assert(math.approxEq(f64, expm1d(0.2), 0.221403, epsilon)); | |
| 280 | assert(math.approxEq(f64, expm1d(0.8923), 1.440737, epsilon)); | |
| 281 | assert(math.approxEq(f64, expm1d(1.5), 3.481689, epsilon)); | |
| 280 | assert(expm1_64(0.0) == 0.0); | |
| 281 | assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon)); | |
| 282 | assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon)); | |
| 283 | assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon)); | |
| 284 | assert(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon)); | |
| 282 | 285 | } |
std/math/fabs.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn fabs(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const fabs = fabs_workaround; | |
| 6 | ||
| 7 | pub fn fabs_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(fabs32, x), |
| ... | ... | @@ -22,17 +25,17 @@ fn fabs64(x: f64) -> f64 { |
| 22 | 25 | @bitCast(f64, u) |
| 23 | 26 | } |
| 24 | 27 | |
| 25 | test "fabs" { | |
| 28 | test "math.fabs" { | |
| 26 | 29 | assert(fabs(f32(1.0)) == fabs32(1.0)); |
| 27 | 30 | assert(fabs(f64(1.0)) == fabs64(1.0)); |
| 28 | 31 | } |
| 29 | 32 | |
| 30 | test "fabs32" { | |
| 33 | test "math.fabs32" { | |
| 31 | 34 | assert(fabs64(1.0) == 1.0); |
| 32 | 35 | assert(fabs64(-1.0) == 1.0); |
| 33 | 36 | } |
| 34 | 37 | |
| 35 | test "fabs64" { | |
| 38 | test "math.fabs64" { | |
| 36 | 39 | assert(fabs64(1.0) == 1.0); |
| 37 | 40 | assert(fabs64(-1.0) == 1.0); |
| 38 | 41 | } |
std/math/floor.zig+7-4| ... | ... | @@ -2,7 +2,10 @@ const builtin = @import("builtin"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | const math = @import("index.zig"); |
| 4 | 4 | |
| 5 | pub fn floor(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const floor = floor_workaround; | |
| 7 | ||
| 8 | pub fn floor_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | 11 | f32 => @inlineCall(floor32, x), |
| ... | ... | @@ -71,18 +74,18 @@ fn floor64(x: f64) -> f64 { |
| 71 | 74 | } |
| 72 | 75 | } |
| 73 | 76 | |
| 74 | test "floor" { | |
| 77 | test "math.floor" { | |
| 75 | 78 | assert(floor(f32(1.3)) == floor32(1.3)); |
| 76 | 79 | assert(floor(f64(1.3)) == floor64(1.3)); |
| 77 | 80 | } |
| 78 | 81 | |
| 79 | test "floor32" { | |
| 82 | test "math.floor32" { | |
| 80 | 83 | assert(floor32(1.3) == 1.0); |
| 81 | 84 | assert(floor32(-1.3) == -2.0); |
| 82 | 85 | assert(floor32(0.2) == 0.0); |
| 83 | 86 | } |
| 84 | 87 | |
| 85 | test "floor64" { | |
| 88 | test "math.floor64" { | |
| 86 | 89 | assert(floor64(1.3) == 1.0); |
| 87 | 90 | assert(floor64(-1.3) == -2.0); |
| 88 | 91 | assert(floor64(0.2) == 0.0); |
std/math/fma.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn fma(comptime T: type, x: T, y: T, z: T) -> T { | |
| 4 | // TODO issue #393 | |
| 5 | pub const fma = fma_workaround; | |
| 6 | ||
| 7 | pub fn fma_workaround(comptime T: type, x: T, y: T, z: T) -> T { | |
| 5 | 8 | switch (T) { |
| 6 | 9 | f32 => @inlineCall(fma32, x, y, z), |
| 7 | 10 | f64 => @inlineCall(fma64, x, y ,z), |
| ... | ... | @@ -130,12 +133,12 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 { |
| 130 | 133 | math.scalbn(sum.hi, scale) |
| 131 | 134 | } |
| 132 | 135 | |
| 133 | test "fma" { | |
| 136 | test "math.fma" { | |
| 134 | 137 | assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0)); |
| 135 | 138 | assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0)); |
| 136 | 139 | } |
| 137 | 140 | |
| 138 | test "fma32" { | |
| 141 | test "math.fma32" { | |
| 139 | 142 | const epsilon = 0.000001; |
| 140 | 143 | |
| 141 | 144 | assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon)); |
| ... | ... | @@ -147,7 +150,7 @@ test "fma32" { |
| 147 | 150 | assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); |
| 148 | 151 | } |
| 149 | 152 | |
| 150 | test "fma64" { | |
| 153 | test "math.fma64" { | |
| 151 | 154 | const epsilon = 0.000001; |
| 152 | 155 | |
| 153 | 156 | assert(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon)); |
std/math/fmod.zig deleted-190| ... | ... | @@ -1,190 +0,0 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 3 | ||
| 4 | pub fn fmod(comptime T: type, x: T, y: T) -> T { | |
| 5 | switch (T) { | |
| 6 | f32 => @inlineCall(fmod32, x, y), | |
| 7 | f64 => @inlineCall(fmod64, x, y), | |
| 8 | else => @compileError("fmod not implemented for " ++ @typeName(T)), | |
| 9 | } | |
| 10 | } | |
| 11 | ||
| 12 | fn fmod32(x: f32, y: f32) -> f32 { | |
| 13 | var ux = @bitCast(u32, x); | |
| 14 | var uy = @bitCast(u32, y); | |
| 15 | var ex = i32(ux >> 23) & 0xFF; | |
| 16 | var ey = i32(ux >> 23) & 0xFF; | |
| 17 | const sx = ux & 0x80000000; | |
| 18 | ||
| 19 | if (uy << 1 == 0 or math.isNan(y) or ex == 0xFF) { | |
| 20 | return (x * y) / (x * y); | |
| 21 | } | |
| 22 | if (ux << 1 <= uy << 1) { | |
| 23 | if (ux << 1 == uy << 1) { | |
| 24 | return 0 * x; | |
| 25 | } else { | |
| 26 | return x; | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 30 | // normalize x and y | |
| 31 | if (ex == 0) { | |
| 32 | var i = ux << 9; | |
| 33 | while (i >> 31 == 0) : (i <<= 1) { | |
| 34 | ex -= 1; | |
| 35 | } | |
| 36 | ux <<= u32(-ex + 1); | |
| 37 | } else { | |
| 38 | ux &= @maxValue(u32) >> 9; | |
| 39 | ux |= 1 << 23; | |
| 40 | } | |
| 41 | ||
| 42 | if (ey == 0) { | |
| 43 | var i = uy << 9; | |
| 44 | while (i >> 31 == 0) : (i <<= 1) { | |
| 45 | ey -= 1; | |
| 46 | } | |
| 47 | uy <<= u32(-ey + 1); | |
| 48 | } else { | |
| 49 | uy &= @maxValue(u32) >> 9; | |
| 50 | uy |= 1 << 23; | |
| 51 | } | |
| 52 | ||
| 53 | // x mod y | |
| 54 | while (ex > ey) : (ex -= 1) { | |
| 55 | const i = ux - uy; | |
| 56 | if (i >> 31 == 0) { | |
| 57 | if (i == 0) { | |
| 58 | return 0 * x; | |
| 59 | } | |
| 60 | ux = i; | |
| 61 | } | |
| 62 | ux <<= 1; | |
| 63 | } | |
| 64 | { | |
| 65 | const i = ux - uy; | |
| 66 | if (i >> 31 == 0) { | |
| 67 | if (i == 0) { | |
| 68 | return 0 * x; | |
| 69 | } | |
| 70 | ux = i; | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | while (ux >> 23 == 0) : (ux <<= 1) { | |
| 75 | ex -= 1; | |
| 76 | } | |
| 77 | ||
| 78 | // scale result up | |
| 79 | if (ex > 0) { | |
| 80 | ux -= 1 << 23; | |
| 81 | ux |= u32(ex) << 23; | |
| 82 | } else { | |
| 83 | ux >>= u32(-ex + 1); | |
| 84 | } | |
| 85 | ||
| 86 | ux |= sx; | |
| 87 | @bitCast(f32, ux) | |
| 88 | } | |
| 89 | ||
| 90 | fn fmod64(x: f64, y: f64) -> f64 { | |
| 91 | var ux = @bitCast(u64, x); | |
| 92 | var uy = @bitCast(u64, y); | |
| 93 | var ex = i32(ux >> 52) & 0x7FF; | |
| 94 | var ey = i32(ux >> 52) & 0x7FF; | |
| 95 | const sx = ux >> 63; | |
| 96 | ||
| 97 | if (uy << 1 == 0 or math.isNan(y) or ex == 0x7FF) { | |
| 98 | return (x * y) / (x * y); | |
| 99 | } | |
| 100 | if (ux << 1 <= uy << 1) { | |
| 101 | if (ux << 1 == uy << 1) { | |
| 102 | return 0 * x; | |
| 103 | } else { | |
| 104 | return x; | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | // normalize x and y | |
| 109 | if (ex == 0) { | |
| 110 | var i = ux << 12; | |
| 111 | while (i >> 63 == 0) : (i <<= 1) { | |
| 112 | ex -= 1; | |
| 113 | } | |
| 114 | ux <<= u64(-ex + 1); | |
| 115 | } else { | |
| 116 | ux &= @maxValue(u64) >> 12; | |
| 117 | ux |= 1 << 52; | |
| 118 | } | |
| 119 | ||
| 120 | if (ey == 0) { | |
| 121 | var i = uy << 12; | |
| 122 | while (i >> 63 == 0) : (i <<= 1) { | |
| 123 | ey -= 1; | |
| 124 | } | |
| 125 | uy <<= u64(-ey + 1); | |
| 126 | } else { | |
| 127 | uy &= @maxValue(u64) >> 12; | |
| 128 | uy |= 1 << 52; | |
| 129 | } | |
| 130 | ||
| 131 | // x mod y | |
| 132 | while (ex > ey) : (ex -= 1) { | |
| 133 | const i = ux - uy; | |
| 134 | if (i >> 63 == 0) { | |
| 135 | if (i == 0) { | |
| 136 | return 0 * x; | |
| 137 | } | |
| 138 | ux = i; | |
| 139 | } | |
| 140 | ux <<= 1; | |
| 141 | } | |
| 142 | { | |
| 143 | const i = ux - uy; | |
| 144 | if (i >> 63 == 0) { | |
| 145 | if (i == 0) { | |
| 146 | return 0 * x; | |
| 147 | } | |
| 148 | ux = i; | |
| 149 | } | |
| 150 | } | |
| 151 | ||
| 152 | while (ux >> 52 == 0) : (ux <<= 1) { | |
| 153 | ex -= 1; | |
| 154 | } | |
| 155 | ||
| 156 | // scale result up | |
| 157 | if (ex > 0) { | |
| 158 | ux -= 1 << 52; | |
| 159 | ux |= u64(ex) << 52; | |
| 160 | } else { | |
| 161 | ux >>= u64(-ex + 1); | |
| 162 | } | |
| 163 | ||
| 164 | ux |= sx << 63; | |
| 165 | @bitCast(f64, ux) | |
| 166 | } | |
| 167 | ||
| 168 | // duplicate symbol clash with `fmod` test name | |
| 169 | test "fmod_" { | |
| 170 | assert(fmod(f32, 1.3, 2.5) == fmod32(1.3, 2.5)); | |
| 171 | assert(fmod(f64, 1.3, 2.5) == fmod64(1.3, 2.5)); | |
| 172 | } | |
| 173 | ||
| 174 | test "fmod32" { | |
| 175 | const epsilon = 0.000001; | |
| 176 | ||
| 177 | assert(math.approxEq(f32, fmod32(5.2, 2.0), 1.2, epsilon)); | |
| 178 | assert(math.approxEq(f32, fmod32(18.5, 4.2), 1.7, epsilon)); | |
| 179 | assert(math.approxEq(f32, fmod32(23, 48.34), 23.0, epsilon)); | |
| 180 | assert(math.approxEq(f32, fmod32(123.340890, 2398.2314), 123.340889, epsilon)); | |
| 181 | } | |
| 182 | ||
| 183 | test "fmod64" { | |
| 184 | const epsilon = 0.000001; | |
| 185 | ||
| 186 | assert(math.approxEq(f64, fmod64(5.2, 2.0), 1.2, epsilon)); | |
| 187 | assert(math.approxEq(f64, fmod64(18.5, 4.2), 1.7, epsilon)); | |
| 188 | assert(math.approxEq(f64, fmod64(23, 48.34), 23.0, epsilon)); | |
| 189 | assert(math.approxEq(f64, fmod64(123.340890, 2398.2314), 123.340889, epsilon)); | |
| 190 | } |
std/math/frexp.zig+7-4| ... | ... | @@ -1,6 +1,9 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | // TODO issue #393 | |
| 5 | pub const frexp = frexp_workaround; | |
| 6 | ||
| 4 | 7 | fn frexp_result(comptime T: type) -> type { |
| 5 | 8 | struct { |
| 6 | 9 | significand: T, |
| ... | ... | @@ -10,7 +13,7 @@ fn frexp_result(comptime T: type) -> type { |
| 10 | 13 | pub const frexp32_result = frexp_result(f32); |
| 11 | 14 | pub const frexp64_result = frexp_result(f64); |
| 12 | 15 | |
| 13 | pub fn frexp(x: var) -> frexp_result(@typeOf(x)) { | |
| 16 | pub fn frexp_workaround(x: var) -> frexp_result(@typeOf(x)) { | |
| 14 | 17 | const T = @typeOf(x); |
| 15 | 18 | switch (T) { |
| 16 | 19 | f32 => @inlineCall(frexp32, x), |
| ... | ... | @@ -80,7 +83,7 @@ fn frexp64(x: f64) -> frexp64_result { |
| 80 | 83 | result |
| 81 | 84 | } |
| 82 | 85 | |
| 83 | test "frexp" { | |
| 86 | test "math.frexp" { | |
| 84 | 87 | const a = frexp(f32(1.3)); |
| 85 | 88 | const b = frexp32(1.3); |
| 86 | 89 | assert(a.significand == b.significand and a.exponent == b.exponent); |
| ... | ... | @@ -90,7 +93,7 @@ test "frexp" { |
| 90 | 93 | assert(c.significand == d.significand and c.exponent == d.exponent); |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | test "frexp32" { | |
| 96 | test "math.frexp32" { | |
| 94 | 97 | const epsilon = 0.000001; |
| 95 | 98 | var r: frexp32_result = undefined; |
| 96 | 99 | |
| ... | ... | @@ -101,7 +104,7 @@ test "frexp32" { |
| 101 | 104 | assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7); |
| 102 | 105 | } |
| 103 | 106 | |
| 104 | test "frexp64" { | |
| 107 | test "math.frexp64" { | |
| 105 | 108 | const epsilon = 0.000001; |
| 106 | 109 | var r: frexp64_result = undefined; |
| 107 | 110 |
std/math/hypot.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn hypot(comptime T: type, x: T, y: T) -> T { | |
| 4 | // TODO issue #393 | |
| 5 | pub const hypot = hypot_workaround; | |
| 6 | ||
| 7 | pub fn hypot_workaround(comptime T: type, x: T, y: T) -> T { | |
| 5 | 8 | switch (T) { |
| 6 | 9 | f32 => @inlineCall(hypot32, x, y), |
| 7 | 10 | f64 => @inlineCall(hypot64, x, y), |
| ... | ... | @@ -105,12 +108,12 @@ fn hypot64(x: f64, y: f64) -> f64 { |
| 105 | 108 | z * math.sqrt(ly + lx + hy + hx) |
| 106 | 109 | } |
| 107 | 110 | |
| 108 | test "hypot" { | |
| 111 | test "math.hypot" { | |
| 109 | 112 | assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2)); |
| 110 | 113 | assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2)); |
| 111 | 114 | } |
| 112 | 115 | |
| 113 | test "hypot32" { | |
| 116 | test "math.hypot32" { | |
| 114 | 117 | const epsilon = 0.000001; |
| 115 | 118 | |
| 116 | 119 | assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon)); |
| ... | ... | @@ -122,7 +125,7 @@ test "hypot32" { |
| 122 | 125 | assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon)); |
| 123 | 126 | } |
| 124 | 127 | |
| 125 | test "hypot64" { | |
| 128 | test "math.hypot64" { | |
| 126 | 129 | const epsilon = 0.000001; |
| 127 | 130 | |
| 128 | 131 | assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon)); |
std/math/ilogb.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn ilogb(x: var) -> i32 { | |
| 4 | // TODO issue #393 | |
| 5 | pub const ilogb = ilogb_workaround; | |
| 6 | ||
| 7 | pub fn ilogb_workaround(x: var) -> i32 { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(ilogb32, x), |
| ... | ... | @@ -76,12 +79,12 @@ fn ilogb64(x: f64) -> i32 { |
| 76 | 79 | e - 0x3FF |
| 77 | 80 | } |
| 78 | 81 | |
| 79 | test "ilogb" { | |
| 82 | test "math.ilogb" { | |
| 80 | 83 | assert(ilogb(f32(0.2)) == ilogb32(0.2)); |
| 81 | 84 | assert(ilogb(f64(0.2)) == ilogb64(0.2)); |
| 82 | 85 | } |
| 83 | 86 | |
| 84 | test "ilogb32" { | |
| 87 | test "math.ilogb32" { | |
| 85 | 88 | assert(ilogb32(0.0) == fp_ilogb0); |
| 86 | 89 | assert(ilogb32(0.5) == -1); |
| 87 | 90 | assert(ilogb32(0.8923) == -1); |
| ... | ... | @@ -90,7 +93,7 @@ test "ilogb32" { |
| 90 | 93 | assert(ilogb32(2398.23) == 11); |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | test "ilogb64" { | |
| 96 | test "math.ilogb64" { | |
| 94 | 97 | assert(ilogb64(0.0) == fp_ilogb0); |
| 95 | 98 | assert(ilogb64(0.5) == -1); |
| 96 | 99 | assert(ilogb64(0.8923) == -1); |
std/math/index.zig-2| ... | ... | @@ -98,7 +98,6 @@ pub const round = @import("round.zig").round; |
| 98 | 98 | pub const frexp = @import("frexp.zig").frexp; |
| 99 | 99 | pub const frexp32_result = @import("frexp.zig").frexp32_result; |
| 100 | 100 | pub const frexp64_result = @import("frexp.zig").frexp64_result; |
| 101 | pub const fmod = @import("fmod.zig").fmod; | |
| 102 | 101 | pub const modf = @import("modf.zig").modf; |
| 103 | 102 | pub const modf32_result = @import("modf.zig").modf32_result; |
| 104 | 103 | pub const modf64_result = @import("modf.zig").modf64_result; |
| ... | ... | @@ -147,7 +146,6 @@ test "math" { |
| 147 | 146 | _ = @import("trunc.zig"); |
| 148 | 147 | _ = @import("round.zig"); |
| 149 | 148 | _ = @import("frexp.zig"); |
| 150 | _ = @import("fmod.zig"); | |
| 151 | 149 | _ = @import("modf.zig"); |
| 152 | 150 | _ = @import("copysign.zig"); |
| 153 | 151 | _ = @import("isfinite.zig"); |
std/math/isfinite.zig+1-1| ... | ... | @@ -18,7 +18,7 @@ pub fn isFinite(x: var) -> bool { |
| 18 | 18 | } |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | test "isFinite" { | |
| 21 | test "math.isFinite" { | |
| 22 | 22 | assert(isFinite(f32(0.0))); |
| 23 | 23 | assert(isFinite(f32(-0.0))); |
| 24 | 24 | assert(isFinite(f64(0.0))); |
std/math/isinf.zig+3-3| ... | ... | @@ -48,7 +48,7 @@ pub fn isNegativeInf(x: var) -> bool { |
| 48 | 48 | } |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | test "isInf" { | |
| 51 | test "math.isInf" { | |
| 52 | 52 | assert(!isInf(f32(0.0))); |
| 53 | 53 | assert(!isInf(f32(-0.0))); |
| 54 | 54 | assert(!isInf(f64(0.0))); |
| ... | ... | @@ -59,7 +59,7 @@ test "isInf" { |
| 59 | 59 | assert(isInf(-math.inf(f64))); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | test "isPositiveInf" { | |
| 62 | test "math.isPositiveInf" { | |
| 63 | 63 | assert(!isPositiveInf(f32(0.0))); |
| 64 | 64 | assert(!isPositiveInf(f32(-0.0))); |
| 65 | 65 | assert(!isPositiveInf(f64(0.0))); |
| ... | ... | @@ -70,7 +70,7 @@ test "isPositiveInf" { |
| 70 | 70 | assert(!isPositiveInf(-math.inf(f64))); |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | test "isNegativeInf" { | |
| 73 | test "math.isNegativeInf" { | |
| 74 | 74 | assert(!isNegativeInf(f32(0.0))); |
| 75 | 75 | assert(!isNegativeInf(f32(-0.0))); |
| 76 | 76 | assert(!isNegativeInf(f64(0.0))); |
std/math/isnan.zig+1-1| ... | ... | @@ -18,7 +18,7 @@ pub fn isNan(x: var) -> bool { |
| 18 | 18 | } |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | test "isNan" { | |
| 21 | test "math.isNan" { | |
| 22 | 22 | assert(isNan(math.nan(f32))); |
| 23 | 23 | assert(isNan(math.nan(f64))); |
| 24 | 24 | assert(!isNan(f32(1.0))); |
std/math/isnormal.zig+1-1| ... | ... | @@ -18,7 +18,7 @@ pub fn isNormal(x: var) -> bool { |
| 18 | 18 | } |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | test "isNormal" { | |
| 21 | test "math.isNormal" { | |
| 22 | 22 | assert(!isNormal(math.nan(f32))); |
| 23 | 23 | assert(!isNormal(math.nan(f64))); |
| 24 | 24 | assert(isNormal(f32(1.0))); |
std/math/ln.zig+3-1| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn ln(x: var) -> @typeOf(x) { | |
| 4 | pub const ln = ln_workaround; | |
| 5 | ||
| 6 | pub fn ln_workaround(x: var) -> @typeOf(x) { | |
| 5 | 7 | const T = @typeOf(x); |
| 6 | 8 | switch (T) { |
| 7 | 9 | f32 => @inlineCall(lnf, x), |
std/math/log.zig+17-25| ... | ... | @@ -2,7 +2,10 @@ const math = @import("index.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const assert = @import("../debug.zig").assert; |
| 4 | 4 | |
| 5 | pub fn log(comptime base: usize, x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const log = log_workaround; | |
| 7 | ||
| 8 | pub fn log_workaround(comptime base: usize, x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (@typeId(T)) { |
| 8 | 11 | builtin.TypeId.Int => { |
| ... | ... | @@ -13,41 +16,30 @@ pub fn log(comptime base: usize, x: var) -> @typeOf(x) { |
| 13 | 16 | } |
| 14 | 17 | }, |
| 15 | 18 | |
| 16 | builtin.TypeId.Float => { | |
| 17 | return logf(base, x); | |
| 18 | }, | |
| 19 | ||
| 20 | else => { | |
| 21 | @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'"); | |
| 22 | }, | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | fn logf(comptime base: usize, x: var) -> @typeOf(x) { | |
| 27 | const T = @typeOf(x); | |
| 28 | switch (T) { | |
| 29 | f32 => { | |
| 30 | switch (base) { | |
| 19 | builtin.TypeId.Float => switch (T) { | |
| 20 | f32 => switch (base) { | |
| 31 | 21 | 2 => return math.log2(x), |
| 32 | 22 | 10 => return math.log10(x), |
| 33 | 23 | else => return f32(math.ln(f64(x)) / math.ln(f64(base))), |
| 34 | } | |
| 35 | }, | |
| 24 | }, | |
| 36 | 25 | |
| 37 | f64 => { | |
| 38 | switch (base) { | |
| 26 | f64 => switch (base) { | |
| 39 | 27 | 2 => return math.log2(x), |
| 40 | 28 | 10 => return math.log10(x), |
| 41 | 29 | // NOTE: This likely is computed with reduced accuracy. |
| 42 | 30 | else => return math.ln(x) / math.ln(f64(base)), |
| 43 | } | |
| 31 | }, | |
| 32 | ||
| 33 | else => @compileError("log not implemented for " ++ @typeName(T)), | |
| 44 | 34 | }, |
| 45 | 35 | |
| 46 | else => @compileError("log not implemented for " ++ @typeName(T)), | |
| 36 | else => { | |
| 37 | @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'"); | |
| 38 | }, | |
| 47 | 39 | } |
| 48 | 40 | } |
| 49 | 41 | |
| 50 | test "log_integer" { | |
| 42 | test "math.log integer" { | |
| 51 | 43 | assert(log(2, u8(0x1)) == 0); |
| 52 | 44 | assert(log(2, u8(0x2)) == 1); |
| 53 | 45 | assert(log(2, i16(0x72)) == 6); |
| ... | ... | @@ -55,7 +47,7 @@ test "log_integer" { |
| 55 | 47 | assert(log(2, u64(0x7FF0123456789ABC)) == 62); |
| 56 | 48 | } |
| 57 | 49 | |
| 58 | test "log_float" { | |
| 50 | test "math.log float" { | |
| 59 | 51 | const epsilon = 0.000001; |
| 60 | 52 | |
| 61 | 53 | assert(math.approxEq(f32, log(6, f32(0.23947)), -0.797723, epsilon)); |
| ... | ... | @@ -63,7 +55,7 @@ test "log_float" { |
| 63 | 55 | assert(math.approxEq(f64, log(123897, f64(12389216414)), 1.981724596, epsilon)); |
| 64 | 56 | } |
| 65 | 57 | |
| 66 | test "log_float_special" { | |
| 58 | test "math.log float_special" { | |
| 67 | 59 | assert(log(2, f32(0.2301974)) == math.log2(f32(0.2301974))); |
| 68 | 60 | assert(log(10, f32(0.2301974)) == math.log10(f32(0.2301974))); |
| 69 | 61 |
std/math/log10.zig+25-22| ... | ... | @@ -1,16 +1,19 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn log10(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const log10 = log10_workaround; | |
| 6 | ||
| 7 | pub fn log10_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(log10f, x), | |
| 8 | f64 => @inlineCall(log10d, x), | |
| 10 | f32 => @inlineCall(log10_32, x), | |
| 11 | f64 => @inlineCall(log10_64, x), | |
| 9 | 12 | else => @compileError("log10 not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | fn log10f(x_: f32) -> f32 { | |
| 16 | fn log10_32(x_: f32) -> f32 { | |
| 14 | 17 | const ivln10hi: f32 = 4.3432617188e-01; |
| 15 | 18 | const ivln10lo: f32 = -3.1689971365e-05; |
| 16 | 19 | const log10_2hi: f32 = 3.0102920532e-01; |
| ... | ... | @@ -70,7 +73,7 @@ fn log10f(x_: f32) -> f32 { |
| 70 | 73 | dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi |
| 71 | 74 | } |
| 72 | 75 | |
| 73 | fn log10d(x_: f64) -> f64 { | |
| 76 | fn log10_64(x_: f64) -> f64 { | |
| 74 | 77 | const ivln10hi: f64 = 4.34294481878168880939e-01; |
| 75 | 78 | const ivln10lo: f64 = 2.50829467116452752298e-11; |
| 76 | 79 | const log10_2hi: f64 = 3.01029995663611771306e-01; |
| ... | ... | @@ -147,29 +150,29 @@ fn log10d(x_: f64) -> f64 { |
| 147 | 150 | val_lo + val_hi |
| 148 | 151 | } |
| 149 | 152 | |
| 150 | test "log10" { | |
| 151 | assert(log10(f32(0.2)) == log10f(0.2)); | |
| 152 | assert(log10(f64(0.2)) == log10d(0.2)); | |
| 153 | test "math.log10" { | |
| 154 | assert(log10(f32(0.2)) == log10_32(0.2)); | |
| 155 | assert(log10(f64(0.2)) == log10_64(0.2)); | |
| 153 | 156 | } |
| 154 | 157 | |
| 155 | test "log10f" { | |
| 158 | test "math.log10_32" { | |
| 156 | 159 | const epsilon = 0.000001; |
| 157 | 160 | |
| 158 | assert(math.approxEq(f32, log10f(0.2), -0.698970, epsilon)); | |
| 159 | assert(math.approxEq(f32, log10f(0.8923), -0.049489, epsilon)); | |
| 160 | assert(math.approxEq(f32, log10f(1.5), 0.176091, epsilon)); | |
| 161 | assert(math.approxEq(f32, log10f(37.45), 1.573452, epsilon)); | |
| 162 | assert(math.approxEq(f32, log10f(89.123), 1.94999, epsilon)); | |
| 163 | assert(math.approxEq(f32, log10f(123123.234375), 5.09034, epsilon)); | |
| 161 | assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon)); | |
| 162 | assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon)); | |
| 163 | assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon)); | |
| 164 | assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon)); | |
| 165 | assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon)); | |
| 166 | assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon)); | |
| 164 | 167 | } |
| 165 | 168 | |
| 166 | test "log10d" { | |
| 169 | test "math.log10_64" { | |
| 167 | 170 | const epsilon = 0.000001; |
| 168 | 171 | |
| 169 | assert(math.approxEq(f64, log10d(0.2), -0.698970, epsilon)); | |
| 170 | assert(math.approxEq(f64, log10d(0.8923), -0.049489, epsilon)); | |
| 171 | assert(math.approxEq(f64, log10d(1.5), 0.176091, epsilon)); | |
| 172 | assert(math.approxEq(f64, log10d(37.45), 1.573452, epsilon)); | |
| 173 | assert(math.approxEq(f64, log10d(89.123), 1.94999, epsilon)); | |
| 174 | assert(math.approxEq(f64, log10d(123123.234375), 5.09034, epsilon)); | |
| 172 | assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon)); | |
| 173 | assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon)); | |
| 174 | assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon)); | |
| 175 | assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon)); | |
| 176 | assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon)); | |
| 177 | assert(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon)); | |
| 175 | 178 | } |
std/math/log1p.zig+27-24| ... | ... | @@ -1,16 +1,19 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn log1p(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const log1p = log1p_workaround; | |
| 6 | ||
| 7 | pub fn log1p_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(log1pf, x), | |
| 8 | f64 => @inlineCall(log1pd, x), | |
| 10 | f32 => @inlineCall(log1p_32, x), | |
| 11 | f64 => @inlineCall(log1p_64, x), | |
| 9 | 12 | else => @compileError("log1p not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | fn log1pf(x: f32) -> f32 { | |
| 16 | fn log1p_32(x: f32) -> f32 { | |
| 14 | 17 | const ln2_hi = 6.9313812256e-01; |
| 15 | 18 | const ln2_lo = 9.0580006145e-06; |
| 16 | 19 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -86,7 +89,7 @@ fn log1pf(x: f32) -> f32 { |
| 86 | 89 | s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi |
| 87 | 90 | } |
| 88 | 91 | |
| 89 | fn log1pd(x: f64) -> f64 { | |
| 92 | fn log1p_64(x: f64) -> f64 { | |
| 90 | 93 | const ln2_hi: f64 = 6.93147180369123816490e-01; |
| 91 | 94 | const ln2_lo: f64 = 1.90821492927058770002e-10; |
| 92 | 95 | const Lg1: f64 = 6.666666666666735130e-01; |
| ... | ... | @@ -167,31 +170,31 @@ fn log1pd(x: f64) -> f64 { |
| 167 | 170 | s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi |
| 168 | 171 | } |
| 169 | 172 | |
| 170 | test "log1p" { | |
| 171 | assert(log1p(f32(0.0)) == log1pf(0.0)); | |
| 172 | assert(log1p(f64(0.0)) == log1pd(0.0)); | |
| 173 | test "math.log1p" { | |
| 174 | assert(log1p(f32(0.0)) == log1p_32(0.0)); | |
| 175 | assert(log1p(f64(0.0)) == log1p_64(0.0)); | |
| 173 | 176 | } |
| 174 | 177 | |
| 175 | test "log1pf" { | |
| 178 | test "math.log1p_32" { | |
| 176 | 179 | const epsilon = 0.000001; |
| 177 | 180 | |
| 178 | assert(math.approxEq(f32, log1pf(0.0), 0.0, epsilon)); | |
| 179 | assert(math.approxEq(f32, log1pf(0.2), 0.182322, epsilon)); | |
| 180 | assert(math.approxEq(f32, log1pf(0.8923), 0.637793, epsilon)); | |
| 181 | assert(math.approxEq(f32, log1pf(1.5), 0.916291, epsilon)); | |
| 182 | assert(math.approxEq(f32, log1pf(37.45), 3.649359, epsilon)); | |
| 183 | assert(math.approxEq(f32, log1pf(89.123), 4.501175, epsilon)); | |
| 184 | assert(math.approxEq(f32, log1pf(123123.234375), 11.720949, epsilon)); | |
| 181 | assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon)); | |
| 182 | assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon)); | |
| 183 | assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon)); | |
| 184 | assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon)); | |
| 185 | assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon)); | |
| 186 | assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon)); | |
| 187 | assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon)); | |
| 185 | 188 | } |
| 186 | 189 | |
| 187 | test "log1pd" { | |
| 190 | test "math.log1p_64" { | |
| 188 | 191 | const epsilon = 0.000001; |
| 189 | 192 | |
| 190 | assert(math.approxEq(f64, log1pd(0.0), 0.0, epsilon)); | |
| 191 | assert(math.approxEq(f64, log1pd(0.2), 0.182322, epsilon)); | |
| 192 | assert(math.approxEq(f64, log1pd(0.8923), 0.637793, epsilon)); | |
| 193 | assert(math.approxEq(f64, log1pd(1.5), 0.916291, epsilon)); | |
| 194 | assert(math.approxEq(f64, log1pd(37.45), 3.649359, epsilon)); | |
| 195 | assert(math.approxEq(f64, log1pd(89.123), 4.501175, epsilon)); | |
| 196 | assert(math.approxEq(f64, log1pd(123123.234375), 11.720949, epsilon)); | |
| 193 | assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon)); | |
| 194 | assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon)); | |
| 195 | assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon)); | |
| 196 | assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon)); | |
| 197 | assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon)); | |
| 198 | assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon)); | |
| 199 | assert(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon)); | |
| 197 | 200 | } |
std/math/log2.zig+23-20| ... | ... | @@ -1,16 +1,19 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn log2(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const log2 = log2_workaround; | |
| 6 | ||
| 7 | pub fn log2_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | f32 => @inlineCall(log2f, x), | |
| 8 | f64 => @inlineCall(log2d, x), | |
| 10 | f32 => @inlineCall(log2_32, x), | |
| 11 | f64 => @inlineCall(log2_64, x), | |
| 9 | 12 | else => @compileError("log2 not implemented for " ++ @typeName(T)), |
| 10 | 13 | } |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | fn log2f(x_: f32) -> f32 { | |
| 16 | fn log2_32(x_: f32) -> f32 { | |
| 14 | 17 | const ivln2hi: f32 = 1.4428710938e+00; |
| 15 | 18 | const ivln2lo: f32 = -1.7605285393e-04; |
| 16 | 19 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -66,7 +69,7 @@ fn log2f(x_: f32) -> f32 { |
| 66 | 69 | (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k) |
| 67 | 70 | } |
| 68 | 71 | |
| 69 | fn log2d(x_: f64) -> f64 { | |
| 72 | fn log2_64(x_: f64) -> f64 { | |
| 70 | 73 | const ivln2hi: f64 = 1.44269504072144627571e+00; |
| 71 | 74 | const ivln2lo: f64 = 1.67517131648865118353e-10; |
| 72 | 75 | const Lg1: f64 = 6.666666666666735130e-01; |
| ... | ... | @@ -139,27 +142,27 @@ fn log2d(x_: f64) -> f64 { |
| 139 | 142 | val_lo + val_hi |
| 140 | 143 | } |
| 141 | 144 | |
| 142 | test "log2" { | |
| 143 | assert(log2(f32(0.2)) == log2f(0.2)); | |
| 144 | assert(log2(f64(0.2)) == log2d(0.2)); | |
| 145 | test "math.log2" { | |
| 146 | assert(log2(f32(0.2)) == log2_32(0.2)); | |
| 147 | assert(log2(f64(0.2)) == log2_64(0.2)); | |
| 145 | 148 | } |
| 146 | 149 | |
| 147 | test "log2f" { | |
| 150 | test "math.log2_32" { | |
| 148 | 151 | const epsilon = 0.000001; |
| 149 | 152 | |
| 150 | assert(math.approxEq(f32, log2f(0.2), -2.321928, epsilon)); | |
| 151 | assert(math.approxEq(f32, log2f(0.8923), -0.164399, epsilon)); | |
| 152 | assert(math.approxEq(f32, log2f(1.5), 0.584962, epsilon)); | |
| 153 | assert(math.approxEq(f32, log2f(37.45), 5.226894, epsilon)); | |
| 154 | assert(math.approxEq(f32, log2f(123123.234375), 16.909744, epsilon)); | |
| 153 | assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon)); | |
| 154 | assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon)); | |
| 155 | assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon)); | |
| 156 | assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon)); | |
| 157 | assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon)); | |
| 155 | 158 | } |
| 156 | 159 | |
| 157 | test "log2d" { | |
| 160 | test "math.log2_64" { | |
| 158 | 161 | const epsilon = 0.000001; |
| 159 | 162 | |
| 160 | assert(math.approxEq(f64, log2d(0.2), -2.321928, epsilon)); | |
| 161 | assert(math.approxEq(f64, log2d(0.8923), -0.164399, epsilon)); | |
| 162 | assert(math.approxEq(f64, log2d(1.5), 0.584962, epsilon)); | |
| 163 | assert(math.approxEq(f64, log2d(37.45), 5.226894, epsilon)); | |
| 164 | assert(math.approxEq(f64, log2d(123123.234375), 16.909744, epsilon)); | |
| 163 | assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon)); | |
| 164 | assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon)); | |
| 165 | assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon)); | |
| 166 | assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon)); | |
| 167 | assert(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon)); | |
| 165 | 168 | } |
std/math/modf.zig+7-4| ... | ... | @@ -1,6 +1,9 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | // TODO issue #393 | |
| 5 | pub const modf = modf_workaround; | |
| 6 | ||
| 4 | 7 | fn modf_result(comptime T: type) -> type { |
| 5 | 8 | struct { |
| 6 | 9 | fpart: T, |
| ... | ... | @@ -10,7 +13,7 @@ fn modf_result(comptime T: type) -> type { |
| 10 | 13 | pub const modf32_result = modf_result(f32); |
| 11 | 14 | pub const modf64_result = modf_result(f64); |
| 12 | 15 | |
| 13 | pub fn modf(x: var) -> modf_result(@typeOf(x)) { | |
| 16 | pub fn modf_workaround(x: var) -> modf_result(@typeOf(x)) { | |
| 14 | 17 | const T = @typeOf(x); |
| 15 | 18 | switch (T) { |
| 16 | 19 | f32 => @inlineCall(modf32, x), |
| ... | ... | @@ -95,7 +98,7 @@ fn modf64(x: f64) -> modf64_result { |
| 95 | 98 | result |
| 96 | 99 | } |
| 97 | 100 | |
| 98 | test "modf" { | |
| 101 | test "math.modf" { | |
| 99 | 102 | const a = modf(f32(1.0)); |
| 100 | 103 | const b = modf32(1.0); |
| 101 | 104 | // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still. |
| ... | ... | @@ -106,7 +109,7 @@ test "modf" { |
| 106 | 109 | assert(a.ipart == b.ipart and a.fpart == b.fpart); |
| 107 | 110 | } |
| 108 | 111 | |
| 109 | test "modf32" { | |
| 112 | test "math.modf32" { | |
| 110 | 113 | const epsilon = 0.000001; |
| 111 | 114 | var r: modf32_result = undefined; |
| 112 | 115 | |
| ... | ... | @@ -131,7 +134,7 @@ test "modf32" { |
| 131 | 134 | assert(math.approxEq(f32, r.fpart, 0.340820, epsilon)); |
| 132 | 135 | } |
| 133 | 136 | |
| 134 | test "modf64" { | |
| 137 | test "math.modf64" { | |
| 135 | 138 | const epsilon = 0.000001; |
| 136 | 139 | var r: modf64_result = undefined; |
| 137 | 140 |
std/math/nan.zig+3-1| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | |
| 3 | pub fn nan(comptime T: type) -> T { | |
| 3 | pub const nan = nan_workaround; | |
| 4 | ||
| 5 | pub fn nan_workaround(comptime T: type) -> T { | |
| 4 | 6 | switch (T) { |
| 5 | 7 | f32 => @bitCast(f32, math.nan_u32), |
| 6 | 8 | f64 => @bitCast(f64, math.nan_u64), |
std/math/oindex.zig deleted-274| ... | ... | @@ -1,274 +0,0 @@ |
| 1 | const assert = @import("../debug.zig").assert; | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | pub const frexp = @import("frexp.zig").frexp; | |
| 5 | ||
| 6 | pub const Cmp = enum { | |
| 7 | Less, | |
| 8 | Equal, | |
| 9 | Greater, | |
| 10 | }; | |
| 11 | ||
| 12 | pub fn min(x: var, y: var) -> @typeOf(x + y) { | |
| 13 | if (x < y) x else y | |
| 14 | } | |
| 15 | ||
| 16 | test "math.min" { | |
| 17 | assert(min(i32(-1), i32(2)) == -1); | |
| 18 | } | |
| 19 | ||
| 20 | pub fn max(x: var, y: var) -> @typeOf(x + y) { | |
| 21 | if (x > y) x else y | |
| 22 | } | |
| 23 | ||
| 24 | test "math.max" { | |
| 25 | assert(max(i32(-1), i32(2)) == 2); | |
| 26 | } | |
| 27 | ||
| 28 | error Overflow; | |
| 29 | pub fn mul(comptime T: type, a: T, b: T) -> %T { | |
| 30 | var answer: T = undefined; | |
| 31 | if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer | |
| 32 | } | |
| 33 | ||
| 34 | error Overflow; | |
| 35 | pub fn add(comptime T: type, a: T, b: T) -> %T { | |
| 36 | var answer: T = undefined; | |
| 37 | if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer | |
| 38 | } | |
| 39 | ||
| 40 | error Overflow; | |
| 41 | pub fn sub(comptime T: type, a: T, b: T) -> %T { | |
| 42 | var answer: T = undefined; | |
| 43 | if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer | |
| 44 | } | |
| 45 | ||
| 46 | pub fn negate(x: var) -> %@typeOf(x) { | |
| 47 | return sub(@typeOf(x), 0, x); | |
| 48 | } | |
| 49 | ||
| 50 | error Overflow; | |
| 51 | pub fn shl(comptime T: type, a: T, b: T) -> %T { | |
| 52 | var answer: T = undefined; | |
| 53 | if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer | |
| 54 | } | |
| 55 | ||
| 56 | test "math overflow functions" { | |
| 57 | testOverflow(); | |
| 58 | comptime testOverflow(); | |
| 59 | } | |
| 60 | ||
| 61 | fn testOverflow() { | |
| 62 | assert(%%mul(i32, 3, 4) == 12); | |
| 63 | assert(%%add(i32, 3, 4) == 7); | |
| 64 | assert(%%sub(i32, 3, 4) == -1); | |
| 65 | assert(%%shl(i32, 0b11, 4) == 0b110000); | |
| 66 | } | |
| 67 | ||
| 68 | ||
| 69 | error Overflow; | |
| 70 | pub fn absInt(x: var) -> %@typeOf(x) { | |
| 71 | const T = @typeOf(x); | |
| 72 | comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt | |
| 73 | comptime assert(T.is_signed); // must pass a signed integer to absInt | |
| 74 | if (x == @minValue(@typeOf(x))) | |
| 75 | return error.Overflow; | |
| 76 | { | |
| 77 | @setDebugSafety(this, false); | |
| 78 | return if (x < 0) -x else x; | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | test "math.absInt" { | |
| 83 | testAbsInt(); | |
| 84 | comptime testAbsInt(); | |
| 85 | } | |
| 86 | fn testAbsInt() { | |
| 87 | assert(%%absInt(i32(-10)) == 10); | |
| 88 | assert(%%absInt(i32(10)) == 10); | |
| 89 | } | |
| 90 | ||
| 91 | pub const absFloat = @import("fabs.zig").fabs; | |
| 92 | ||
| 93 | error DivisionByZero; | |
| 94 | error Overflow; | |
| 95 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 96 | @setDebugSafety(this, false); | |
| 97 | if (denominator == 0) | |
| 98 | return error.DivisionByZero; | |
| 99 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) | |
| 100 | return error.Overflow; | |
| 101 | return @divTrunc(numerator, denominator); | |
| 102 | } | |
| 103 | ||
| 104 | test "math.divTrunc" { | |
| 105 | testDivTrunc(); | |
| 106 | comptime testDivTrunc(); | |
| 107 | } | |
| 108 | fn testDivTrunc() { | |
| 109 | assert(%%divTrunc(i32, 5, 3) == 1); | |
| 110 | assert(%%divTrunc(i32, -5, 3) == -1); | |
| 111 | if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 112 | if (divTrunc(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | |
| 113 | ||
| 114 | assert(%%divTrunc(f32, 5.0, 3.0) == 1.0); | |
| 115 | assert(%%divTrunc(f32, -5.0, 3.0) == -1.0); | |
| 116 | } | |
| 117 | ||
| 118 | error DivisionByZero; | |
| 119 | error Overflow; | |
| 120 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 121 | @setDebugSafety(this, false); | |
| 122 | if (denominator == 0) | |
| 123 | return error.DivisionByZero; | |
| 124 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) | |
| 125 | return error.Overflow; | |
| 126 | return @divFloor(numerator, denominator); | |
| 127 | } | |
| 128 | ||
| 129 | test "math.divFloor" { | |
| 130 | testDivFloor(); | |
| 131 | comptime testDivFloor(); | |
| 132 | } | |
| 133 | fn testDivFloor() { | |
| 134 | assert(%%divFloor(i32, 5, 3) == 1); | |
| 135 | assert(%%divFloor(i32, -5, 3) == -2); | |
| 136 | if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 137 | if (divFloor(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | |
| 138 | ||
| 139 | assert(%%divFloor(f32, 5.0, 3.0) == 1.0); | |
| 140 | assert(%%divFloor(f32, -5.0, 3.0) == -2.0); | |
| 141 | } | |
| 142 | ||
| 143 | error DivisionByZero; | |
| 144 | error Overflow; | |
| 145 | error UnexpectedRemainder; | |
| 146 | pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 147 | @setDebugSafety(this, false); | |
| 148 | if (denominator == 0) | |
| 149 | return error.DivisionByZero; | |
| 150 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) | |
| 151 | return error.Overflow; | |
| 152 | const result = @divTrunc(numerator, denominator); | |
| 153 | if (result * denominator != numerator) | |
| 154 | return error.UnexpectedRemainder; | |
| 155 | return result; | |
| 156 | } | |
| 157 | ||
| 158 | test "math.divExact" { | |
| 159 | testDivExact(); | |
| 160 | comptime testDivExact(); | |
| 161 | } | |
| 162 | fn testDivExact() { | |
| 163 | assert(%%divExact(i32, 10, 5) == 2); | |
| 164 | assert(%%divExact(i32, -10, 5) == -2); | |
| 165 | if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 166 | if (divExact(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | |
| 167 | if (divExact(i32, 5, 2)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder); | |
| 168 | ||
| 169 | assert(%%divExact(f32, 10.0, 5.0) == 2.0); | |
| 170 | assert(%%divExact(f32, -10.0, 5.0) == -2.0); | |
| 171 | if (divExact(f32, 5.0, 2.0)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder); | |
| 172 | } | |
| 173 | ||
| 174 | error DivisionByZero; | |
| 175 | error NegativeDenominator; | |
| 176 | pub fn mod(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 177 | @setDebugSafety(this, false); | |
| 178 | if (denominator == 0) | |
| 179 | return error.DivisionByZero; | |
| 180 | if (denominator < 0) | |
| 181 | return error.NegativeDenominator; | |
| 182 | return @mod(numerator, denominator); | |
| 183 | } | |
| 184 | ||
| 185 | test "math.mod" { | |
| 186 | testMod(); | |
| 187 | comptime testMod(); | |
| 188 | } | |
| 189 | fn testMod() { | |
| 190 | assert(%%mod(i32, -5, 3) == 1); | |
| 191 | assert(%%mod(i32, 5, 3) == 2); | |
| 192 | if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | |
| 193 | if (mod(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 194 | ||
| 195 | assert(%%mod(f32, -5, 3) == 1); | |
| 196 | assert(%%mod(f32, 5, 3) == 2); | |
| 197 | if (mod(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | |
| 198 | if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 199 | } | |
| 200 | ||
| 201 | error DivisionByZero; | |
| 202 | error NegativeDenominator; | |
| 203 | pub fn rem(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 204 | @setDebugSafety(this, false); | |
| 205 | if (denominator == 0) | |
| 206 | return error.DivisionByZero; | |
| 207 | if (denominator < 0) | |
| 208 | return error.NegativeDenominator; | |
| 209 | return @rem(numerator, denominator); | |
| 210 | } | |
| 211 | ||
| 212 | test "math.rem" { | |
| 213 | testRem(); | |
| 214 | comptime testRem(); | |
| 215 | } | |
| 216 | fn testRem() { | |
| 217 | assert(%%rem(i32, -5, 3) == -2); | |
| 218 | assert(%%rem(i32, 5, 3) == 2); | |
| 219 | if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | |
| 220 | if (rem(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 221 | ||
| 222 | assert(%%rem(f32, -5, 3) == -2); | |
| 223 | assert(%%rem(f32, 5, 3) == 2); | |
| 224 | if (rem(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | |
| 225 | if (rem(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | |
| 226 | } | |
| 227 | ||
| 228 | /// Returns the absolute value of the integer parameter. | |
| 229 | /// Result is an unsigned integer. | |
| 230 | pub fn absCast(x: var) -> @IntType(false, @typeOf(x).bit_count) { | |
| 231 | const uint = @IntType(false, @typeOf(x).bit_count); | |
| 232 | if (x >= 0) | |
| 233 | return uint(x); | |
| 234 | ||
| 235 | return uint(-(x + 1)) + 1; | |
| 236 | } | |
| 237 | ||
| 238 | test "math.absCast" { | |
| 239 | assert(absCast(i32(-999)) == 999); | |
| 240 | assert(@typeOf(absCast(i32(-999))) == u32); | |
| 241 | ||
| 242 | assert(absCast(i32(999)) == 999); | |
| 243 | assert(@typeOf(absCast(i32(999))) == u32); | |
| 244 | ||
| 245 | assert(absCast(i32(@minValue(i32))) == -@minValue(i32)); | |
| 246 | assert(@typeOf(absCast(i32(@minValue(i32)))) == u32); | |
| 247 | } | |
| 248 | ||
| 249 | /// Returns the negation of the integer parameter. | |
| 250 | /// Result is a signed integer. | |
| 251 | error Overflow; | |
| 252 | pub fn negateCast(x: var) -> %@IntType(true, @typeOf(x).bit_count) { | |
| 253 | if (@typeOf(x).is_signed) | |
| 254 | return negate(x); | |
| 255 | ||
| 256 | const int = @IntType(true, @typeOf(x).bit_count); | |
| 257 | if (x > -@minValue(int)) | |
| 258 | return error.Overflow; | |
| 259 | ||
| 260 | if (x == -@minValue(int)) | |
| 261 | return @minValue(int); | |
| 262 | ||
| 263 | return -int(x); | |
| 264 | } | |
| 265 | ||
| 266 | test "math.negateCast" { | |
| 267 | assert(%%negateCast(u32(999)) == -999); | |
| 268 | assert(@typeOf(%%negateCast(u32(999))) == i32); | |
| 269 | ||
| 270 | assert(%%negateCast(u32(-@minValue(i32))) == @minValue(i32)); | |
| 271 | assert(@typeOf(%%negateCast(u32(-@minValue(i32)))) == i32); | |
| 272 | ||
| 273 | if (negateCast(u32(@maxValue(i32) + 10))) |_| unreachable else |err| assert(err == error.Overflow); | |
| 274 | } |
std/math/pow.zig+5-4| ... | ... | @@ -1,8 +1,11 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | // TODO issue #393 | |
| 5 | pub const pow = pow_workaround; | |
| 6 | ||
| 4 | 7 | // This implementation is taken from the go stlib, musl is a bit more complex. |
| 5 | pub fn pow(comptime T: type, x: T, y: T) -> T { | |
| 8 | pub fn pow_workaround(comptime T: type, x: T, y: T) -> T { | |
| 6 | 9 | |
| 7 | 10 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 8 | 11 | |
| ... | ... | @@ -158,9 +161,7 @@ test "math.pow" { |
| 158 | 161 | assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon)); |
| 159 | 162 | assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon)); |
| 160 | 163 | assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon)); |
| 161 | ||
| 162 | // TODO: Determine why aborting on release mode. | |
| 163 | // assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon)); | |
| 164 | assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon)); | |
| 164 | 165 | |
| 165 | 166 | // assert(math.approxEq(f32, pow(f64, 0.0, 3.3), 0.0, epsilon)); // TODO: Handle div zero |
| 166 | 167 | assert(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon)); |
std/math/round.zig+7-4| ... | ... | @@ -2,7 +2,10 @@ const builtin = @import("builtin"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | const math = @import("index.zig"); |
| 4 | 4 | |
| 5 | pub fn round(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const round = round_workaround; | |
| 7 | ||
| 8 | pub fn round_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | 11 | f32 => @inlineCall(round32, x), |
| ... | ... | @@ -85,19 +88,19 @@ fn round64(x_: f64) -> f64 { |
| 85 | 88 | } |
| 86 | 89 | } |
| 87 | 90 | |
| 88 | test "round" { | |
| 91 | test "math.round" { | |
| 89 | 92 | assert(round(f32(1.3)) == round32(1.3)); |
| 90 | 93 | assert(round(f64(1.3)) == round64(1.3)); |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | test "round32" { | |
| 96 | test "math.round32" { | |
| 94 | 97 | assert(round32(1.3) == 1.0); |
| 95 | 98 | assert(round32(-1.3) == -1.0); |
| 96 | 99 | assert(round32(0.2) == 0.0); |
| 97 | 100 | assert(round32(1.8) == 2.0); |
| 98 | 101 | } |
| 99 | 102 | |
| 100 | test "round64" { | |
| 103 | test "math.round64" { | |
| 101 | 104 | assert(round64(1.3) == 1.0); |
| 102 | 105 | assert(round64(-1.3) == -1.0); |
| 103 | 106 | assert(round64(0.2) == 0.0); |
std/math/scalbn.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn scalbn(x: var, n: i32) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const scalbn = scalbn_workaround; | |
| 6 | ||
| 7 | pub fn scalbn_workaround(x: var, n: i32) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(scalbn32, x, n), |
| ... | ... | @@ -71,15 +74,15 @@ fn scalbn64(x: f64, n_: i32) -> f64 { |
| 71 | 74 | y * @bitCast(f64, u) |
| 72 | 75 | } |
| 73 | 76 | |
| 74 | test "scalbn" { | |
| 77 | test "math.scalbn" { | |
| 75 | 78 | assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4)); |
| 76 | 79 | assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4)); |
| 77 | 80 | } |
| 78 | 81 | |
| 79 | test "scalbn32" { | |
| 82 | test "math.scalbn32" { | |
| 80 | 83 | assert(scalbn32(1.5, 4) == 24.0); |
| 81 | 84 | } |
| 82 | 85 | |
| 83 | test "scalbn64" { | |
| 86 | test "math.scalbn64" { | |
| 84 | 87 | assert(scalbn64(1.5, 4) == 24.0); |
| 85 | 88 | } |
std/math/signbit.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn signbit(x: var) -> bool { | |
| 4 | // TODO issue #393 | |
| 5 | pub const signbit = signbit_workaround; | |
| 6 | ||
| 7 | pub fn signbit_workaround(x: var) -> bool { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(signbit32, x), |
| ... | ... | @@ -20,17 +23,17 @@ fn signbit64(x: f64) -> bool { |
| 20 | 23 | bits >> 63 != 0 |
| 21 | 24 | } |
| 22 | 25 | |
| 23 | test "signbit" { | |
| 26 | test "math.signbit" { | |
| 24 | 27 | assert(signbit(f32(4.0)) == signbit32(4.0)); |
| 25 | 28 | assert(signbit(f64(4.0)) == signbit64(4.0)); |
| 26 | 29 | } |
| 27 | 30 | |
| 28 | test "signbit32" { | |
| 31 | test "math.signbit32" { | |
| 29 | 32 | assert(!signbit32(4.0)); |
| 30 | 33 | assert(signbit32(-3.0)); |
| 31 | 34 | } |
| 32 | 35 | |
| 33 | test "signbit64" { | |
| 36 | test "math.signbit64" { | |
| 34 | 37 | assert(!signbit64(4.0)); |
| 35 | 38 | assert(signbit64(-3.0)); |
| 36 | 39 | } |
std/math/sin.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn sin(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const sin = sin_workaround; | |
| 6 | ||
| 7 | pub fn sin_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(sin32, x), |
| ... | ... | @@ -135,12 +138,12 @@ fn sin64(x_: f64) -> f64 { |
| 135 | 138 | } |
| 136 | 139 | } |
| 137 | 140 | |
| 138 | test "sin" { | |
| 141 | test "math.sin" { | |
| 139 | 142 | assert(sin(f32(0.0)) == sin32(0.0)); |
| 140 | 143 | assert(sin(f64(0.0)) == sin64(0.0)); |
| 141 | 144 | } |
| 142 | 145 | |
| 143 | test "sin32" { | |
| 146 | test "math.sin32" { | |
| 144 | 147 | const epsilon = 0.000001; |
| 145 | 148 | |
| 146 | 149 | assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); |
| ... | ... | @@ -151,7 +154,7 @@ test "sin32" { |
| 151 | 154 | assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon)); |
| 152 | 155 | } |
| 153 | 156 | |
| 154 | test "sin64" { | |
| 157 | test "math.sin64" { | |
| 155 | 158 | const epsilon = 0.000001; |
| 156 | 159 | |
| 157 | 160 | assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon)); |
std/math/sinh.zig+21-18| ... | ... | @@ -2,11 +2,14 @@ const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | const expo2 = @import("_expo2.zig").expo2; |
| 4 | 4 | |
| 5 | pub fn sinh(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const sinh = sinh_workaround; | |
| 7 | ||
| 8 | pub fn sinh_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | f32 => @inlineCall(sinhf, x), | |
| 9 | f64 => @inlineCall(sinhd, x), | |
| 11 | f32 => @inlineCall(sinh32, x), | |
| 12 | f64 => @inlineCall(sinh64, x), | |
| 10 | 13 | else => @compileError("sinh not implemented for " ++ @typeName(T)), |
| 11 | 14 | } |
| 12 | 15 | } |
| ... | ... | @@ -14,7 +17,7 @@ pub fn sinh(x: var) -> @typeOf(x) { |
| 14 | 17 | // sinh(x) = (exp(x) - 1 / exp(x)) / 2 |
| 15 | 18 | // = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 2 |
| 16 | 19 | // = x + x^3 / 6 + o(x^5) |
| 17 | fn sinhf(x: f32) -> f32 { | |
| 20 | fn sinh32(x: f32) -> f32 { | |
| 18 | 21 | const u = @bitCast(u32, x); |
| 19 | 22 | const ux = u & 0x7FFFFFFF; |
| 20 | 23 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -41,7 +44,7 @@ fn sinhf(x: f32) -> f32 { |
| 41 | 44 | 2 * h * expo2(ax) |
| 42 | 45 | } |
| 43 | 46 | |
| 44 | fn sinhd(x: f64) -> f64 { | |
| 47 | fn sinh64(x: f64) -> f64 { | |
| 45 | 48 | const u = @bitCast(u64, x); |
| 46 | 49 | const w = u32(u >> 32); |
| 47 | 50 | const ax = @bitCast(f64, u & (@maxValue(u64) >> 1)); |
| ... | ... | @@ -69,25 +72,25 @@ fn sinhd(x: f64) -> f64 { |
| 69 | 72 | 2 * h * expo2(ax) |
| 70 | 73 | } |
| 71 | 74 | |
| 72 | test "sinh" { | |
| 73 | assert(sinh(f32(1.5)) == sinhf(1.5)); | |
| 74 | assert(sinh(f64(1.5)) == sinhd(1.5)); | |
| 75 | test "math.sinh" { | |
| 76 | assert(sinh(f32(1.5)) == sinh32(1.5)); | |
| 77 | assert(sinh(f64(1.5)) == sinh64(1.5)); | |
| 75 | 78 | } |
| 76 | 79 | |
| 77 | test "sinhf" { | |
| 80 | test "math.sinh32" { | |
| 78 | 81 | const epsilon = 0.000001; |
| 79 | 82 | |
| 80 | assert(math.approxEq(f32, sinhf(0.0), 0.0, epsilon)); | |
| 81 | assert(math.approxEq(f32, sinhf(0.2), 0.201336, epsilon)); | |
| 82 | assert(math.approxEq(f32, sinhf(0.8923), 1.015512, epsilon)); | |
| 83 | assert(math.approxEq(f32, sinhf(1.5), 2.129279, epsilon)); | |
| 83 | assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon)); | |
| 84 | assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon)); | |
| 85 | assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon)); | |
| 86 | assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon)); | |
| 84 | 87 | } |
| 85 | 88 | |
| 86 | test "sinhd" { | |
| 89 | test "math.sinh64" { | |
| 87 | 90 | const epsilon = 0.000001; |
| 88 | 91 | |
| 89 | assert(math.approxEq(f64, sinhd(0.0), 0.0, epsilon)); | |
| 90 | assert(math.approxEq(f64, sinhd(0.2), 0.201336, epsilon)); | |
| 91 | assert(math.approxEq(f64, sinhd(0.8923), 1.015512, epsilon)); | |
| 92 | assert(math.approxEq(f64, sinhd(1.5), 2.129279, epsilon)); | |
| 92 | assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon)); | |
| 93 | assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon)); | |
| 94 | assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon)); | |
| 95 | assert(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon)); | |
| 93 | 96 | } |
std/math/sqrt.zig+7-4| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn sqrt(x: var) -> @typeOf(x) { | |
| 4 | // TODO issue #393 | |
| 5 | pub const sqrt = sqrt_workaround; | |
| 6 | ||
| 7 | pub fn sqrt_workaround(x: var) -> @typeOf(x) { | |
| 5 | 8 | const T = @typeOf(x); |
| 6 | 9 | switch (T) { |
| 7 | 10 | f32 => @inlineCall(sqrt32, x), |
| ... | ... | @@ -219,12 +222,12 @@ fn sqrt64(x: f64) -> f64 { |
| 219 | 222 | @bitCast(f64, uz) |
| 220 | 223 | } |
| 221 | 224 | |
| 222 | test "sqrt" { | |
| 225 | test "math.sqrt" { | |
| 223 | 226 | assert(sqrt(f32(0.0)) == sqrt32(0.0)); |
| 224 | 227 | assert(sqrt(f64(0.0)) == sqrt64(0.0)); |
| 225 | 228 | } |
| 226 | 229 | |
| 227 | test "sqrt32" { | |
| 230 | test "math.sqrt32" { | |
| 228 | 231 | const epsilon = 0.000001; |
| 229 | 232 | |
| 230 | 233 | assert(sqrt32(0.0) == 0.0); |
| ... | ... | @@ -238,7 +241,7 @@ test "sqrt32" { |
| 238 | 241 | assert(math.approxEq(f32, sqrt32(8942.230469), 94.563370, epsilon)); |
| 239 | 242 | } |
| 240 | 243 | |
| 241 | test "sqrt64" { | |
| 244 | test "math.sqrt64" { | |
| 242 | 245 | const epsilon = 0.000001; |
| 243 | 246 | |
| 244 | 247 | assert(sqrt64(0.0) == 0.0); |
std/math/tan.zig+6-4| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn tan(x: var) -> @typeOf(x) { | |
| 4 | pub const tan = tan_workaround; | |
| 5 | ||
| 6 | pub fn tan_workaround(x: var) -> @typeOf(x) { | |
| 5 | 7 | const T = @typeOf(x); |
| 6 | 8 | switch (T) { |
| 7 | 9 | f32 => @inlineCall(tan32, x), |
| ... | ... | @@ -122,12 +124,12 @@ fn tan64(x_: f64) -> f64 { |
| 122 | 124 | r |
| 123 | 125 | } |
| 124 | 126 | |
| 125 | test "tan" { | |
| 127 | test "math.tan" { | |
| 126 | 128 | assert(tan(f32(0.0)) == tan32(0.0)); |
| 127 | 129 | assert(tan(f64(0.0)) == tan64(0.0)); |
| 128 | 130 | } |
| 129 | 131 | |
| 130 | test "tan32" { | |
| 132 | test "math.tan32" { | |
| 131 | 133 | const epsilon = 0.000001; |
| 132 | 134 | |
| 133 | 135 | assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); |
| ... | ... | @@ -138,7 +140,7 @@ test "tan32" { |
| 138 | 140 | assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon)); |
| 139 | 141 | } |
| 140 | 142 | |
| 141 | test "tan64" { | |
| 143 | test "math.tan64" { | |
| 142 | 144 | const epsilon = 0.000001; |
| 143 | 145 | |
| 144 | 146 | assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon)); |
std/math/tanh.zig+23-20| ... | ... | @@ -2,11 +2,14 @@ const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | const expo2 = @import("_expo2.zig").expo2; |
| 4 | 4 | |
| 5 | pub fn tanh(x: var) -> @typeOf(x) { | |
| 5 | // TODO issue #393 | |
| 6 | pub const tanh = tanh_workaround; | |
| 7 | ||
| 8 | pub fn tanh_workaround(x: var) -> @typeOf(x) { | |
| 6 | 9 | const T = @typeOf(x); |
| 7 | 10 | switch (T) { |
| 8 | f32 => @inlineCall(tanhf, x), | |
| 9 | f64 => @inlineCall(tanhd, x), | |
| 11 | f32 => @inlineCall(tanh32, x), | |
| 12 | f64 => @inlineCall(tanh64, x), | |
| 10 | 13 | else => @compileError("tanh not implemented for " ++ @typeName(T)), |
| 11 | 14 | } |
| 12 | 15 | } |
| ... | ... | @@ -14,7 +17,7 @@ pub fn tanh(x: var) -> @typeOf(x) { |
| 14 | 17 | // tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) |
| 15 | 18 | // = (exp(2x) - 1) / (exp(2x) - 1 + 2) |
| 16 | 19 | // = (1 - exp(-2x)) / (exp(-2x) - 1 + 2) |
| 17 | fn tanhf(x: f32) -> f32 { | |
| 20 | fn tanh32(x: f32) -> f32 { | |
| 18 | 21 | const u = @bitCast(u32, x); |
| 19 | 22 | const ux = u & 0x7FFFFFFF; |
| 20 | 23 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -54,7 +57,7 @@ fn tanhf(x: f32) -> f32 { |
| 54 | 57 | } |
| 55 | 58 | } |
| 56 | 59 | |
| 57 | fn tanhd(x: f64) -> f64 { | |
| 60 | fn tanh64(x: f64) -> f64 { | |
| 58 | 61 | const u = @bitCast(u64, x); |
| 59 | 62 | const w = u32(u >> 32); |
| 60 | 63 | const ax = @bitCast(f64, u & (@maxValue(u64) >> 1)); |
| ... | ... | @@ -94,27 +97,27 @@ fn tanhd(x: f64) -> f64 { |
| 94 | 97 | } |
| 95 | 98 | } |
| 96 | 99 | |
| 97 | test "tanh" { | |
| 98 | assert(tanh(f32(1.5)) == tanhf(1.5)); | |
| 99 | assert(tanh(f64(1.5)) == tanhd(1.5)); | |
| 100 | test "math.tanh" { | |
| 101 | assert(tanh(f32(1.5)) == tanh32(1.5)); | |
| 102 | assert(tanh(f64(1.5)) == tanh64(1.5)); | |
| 100 | 103 | } |
| 101 | 104 | |
| 102 | test "tanhf" { | |
| 105 | test "math.tanh32" { | |
| 103 | 106 | const epsilon = 0.000001; |
| 104 | 107 | |
| 105 | assert(math.approxEq(f32, tanhf(0.0), 0.0, epsilon)); | |
| 106 | assert(math.approxEq(f32, tanhf(0.2), 0.197375, epsilon)); | |
| 107 | assert(math.approxEq(f32, tanhf(0.8923), 0.712528, epsilon)); | |
| 108 | assert(math.approxEq(f32, tanhf(1.5), 0.905148, epsilon)); | |
| 109 | assert(math.approxEq(f32, tanhf(37.45), 1.0, epsilon)); | |
| 108 | assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon)); | |
| 109 | assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon)); | |
| 110 | assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon)); | |
| 111 | assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon)); | |
| 112 | assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon)); | |
| 110 | 113 | } |
| 111 | 114 | |
| 112 | test "tanhd" { | |
| 115 | test "math.tanh64" { | |
| 113 | 116 | const epsilon = 0.000001; |
| 114 | 117 | |
| 115 | assert(math.approxEq(f64, tanhd(0.0), 0.0, epsilon)); | |
| 116 | assert(math.approxEq(f64, tanhd(0.2), 0.197375, epsilon)); | |
| 117 | assert(math.approxEq(f64, tanhd(0.8923), 0.712528, epsilon)); | |
| 118 | assert(math.approxEq(f64, tanhd(1.5), 0.905148, epsilon)); | |
| 119 | assert(math.approxEq(f64, tanhd(37.45), 1.0, epsilon)); | |
| 118 | assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon)); | |
| 119 | assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon)); | |
| 120 | assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon)); | |
| 121 | assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon)); | |
| 122 | assert(math.approxEq(f64, tanh64(37.45), 1.0, epsilon)); | |
| 120 | 123 | } |
std/math/trunc.zig+6-4| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | const assert = @import("../debug.zig").assert; |
| 3 | 3 | |
| 4 | pub fn trunc(x: var) -> @typeOf(x) { | |
| 4 | pub const trunc = trunc_workaround; | |
| 5 | ||
| 6 | pub fn trunc_workaround(x: var) -> @typeOf(x) { | |
| 5 | 7 | const T = @typeOf(x); |
| 6 | 8 | switch (T) { |
| 7 | 9 | f32 => @inlineCall(trunc32, x), |
| ... | ... | @@ -52,18 +54,18 @@ fn trunc64(x: f64) -> f64 { |
| 52 | 54 | } |
| 53 | 55 | } |
| 54 | 56 | |
| 55 | test "trunc" { | |
| 57 | test "math.trunc" { | |
| 56 | 58 | assert(trunc(f32(1.3)) == trunc32(1.3)); |
| 57 | 59 | assert(trunc(f64(1.3)) == trunc64(1.3)); |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | test "trunc32" { | |
| 62 | test "math.trunc32" { | |
| 61 | 63 | assert(trunc32(1.3) == 1.0); |
| 62 | 64 | assert(trunc32(-1.3) == -1.0); |
| 63 | 65 | assert(trunc32(0.2) == 0.0); |
| 64 | 66 | } |
| 65 | 67 | |
| 66 | test "trunc64" { | |
| 68 | test "math.trunc64" { | |
| 67 | 69 | assert(trunc64(1.3) == 1.0); |
| 68 | 70 | assert(trunc64(-1.3) == -1.0); |
| 69 | 71 | assert(trunc64(0.2) == 0.0); |