authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-19 14:36:33-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-19 14:36:33-04:00
logc9fc8bd802f5ed52c4cc78b93f18fc5dc9b6bb7f
tree8ddb992d7c1b4ede1b6a99e32fad16c1a476e0c1
parent799c69910172a7248ab9db366e6e3a6556e7d626

workaround for llvm bug

See #393 for details

46 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,6 +438,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
438 }438 }
439439
440 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");440 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");
441 addLLVMFnAttr(fn_table_entry->llvm_value, "nobuiltin");
441 if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {442 if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {
442 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");443 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");
443 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr);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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn acos(x: var) -> @typeOf(x) {4pub const acos = acos_workaround;
5
6// TODO issue #393
7pub fn acos_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(acos32, x),10 f32 => @inlineCall(acos32, x),
...@@ -137,12 +140,12 @@ fn acos64(x: f64) -> f64 {...@@ -137,12 +140,12 @@ fn acos64(x: f64) -> f64 {
137 2 * (df + w)140 2 * (df + w)
138}141}
139142
140test "acos" {143test "math.acos" {
141 assert(acos(f32(0.0)) == acos32(0.0));144 assert(acos_workaround(f32(0.0)) == acos32(0.0));
142 assert(acos(f64(0.0)) == acos64(0.0));145 assert(acos_workaround(f64(0.0)) == acos64(0.0));
143}146}
144147
145test "acos32" {148test "math.acos32" {
146 const epsilon = 0.000001;149 const epsilon = 0.000001;
147150
148 assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));151 assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
...@@ -153,7 +156,7 @@ test "acos32" {...@@ -153,7 +156,7 @@ test "acos32" {
153 assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));156 assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
154}157}
155158
156test "acos64" {159test "math.acos64" {
157 const epsilon = 0.000001;160 const epsilon = 0.000001;
158161
159 assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));162 assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
std/math/acosh.zig+21-18
...@@ -1,17 +1,20 @@...@@ -1,17 +1,20 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn acosh(x: var) -> @typeOf(x) {4pub const acosh = acosh_workaround;
5
6// TODO issue #393
7pub fn acosh_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(acoshf, x),10 f32 => @inlineCall(acosh32, x),
8 f64 => @inlineCall(acoshd, x),11 f64 => @inlineCall(acosh64, x),
9 else => @compileError("acosh not implemented for " ++ @typeName(T)),12 else => @compileError("acosh not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13// acosh(x) = log(x + sqrt(x * x - 1))16// acosh(x) = log(x + sqrt(x * x - 1))
14fn acoshf(x: f32) -> f32 {17fn acosh32(x: f32) -> f32 {
15 const u = @bitCast(u32, x);18 const u = @bitCast(u32, x);
16 const i = u & 0x7FFFFFFF;19 const i = u & 0x7FFFFFFF;
1720
...@@ -29,7 +32,7 @@ fn acoshf(x: f32) -> f32 {...@@ -29,7 +32,7 @@ fn acoshf(x: f32) -> f32 {
29 }32 }
30}33}
3134
32fn acoshd(x: f64) -> f64 {35fn acosh64(x: f64) -> f64 {
33 const u = @bitCast(u64, x);36 const u = @bitCast(u64, x);
34 const e = (u >> 52) & 0x7FF;37 const e = (u >> 52) & 0x7FF;
3538
...@@ -47,25 +50,25 @@ fn acoshd(x: f64) -> f64 {...@@ -47,25 +50,25 @@ fn acoshd(x: f64) -> f64 {
47 }50 }
48}51}
4952
50test "acosh" {53test "math.acosh" {
51 assert(acosh(f32(1.5)) == acoshf(1.5));54 assert(acosh_workaround(f32(1.5)) == acosh32(1.5));
52 assert(acosh(f64(1.5)) == acoshd(1.5));55 assert(acosh_workaround(f64(1.5)) == acosh64(1.5));
53}56}
5457
55test "acoshf" {58test "math.acosh32" {
56 const epsilon = 0.000001;59 const epsilon = 0.000001;
5760
58 assert(math.approxEq(f32, acoshf(1.5), 0.962424, epsilon));61 assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
59 assert(math.approxEq(f32, acoshf(37.45), 4.315976, epsilon));62 assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
60 assert(math.approxEq(f32, acoshf(89.123), 5.183133, epsilon));63 assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
61 assert(math.approxEq(f32, acoshf(123123.234375), 12.414088, epsilon));64 assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
62}65}
6366
64test "acoshd" {67test "math.acosh64" {
65 const epsilon = 0.000001;68 const epsilon = 0.000001;
6669
67 assert(math.approxEq(f64, acoshd(1.5), 0.962424, epsilon));70 assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
68 assert(math.approxEq(f64, acoshd(37.45), 4.315976, epsilon));71 assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
69 assert(math.approxEq(f64, acoshd(89.123), 5.183133, epsilon));72 assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
70 assert(math.approxEq(f64, acoshd(123123.234375), 12.414088, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn asin(x: var) -> @typeOf(x) {4pub const asin = asin_workaround;
5
6// TODO issue #393
7pub fn asin_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(asin32, x),10 f32 => @inlineCall(asin32, x),
...@@ -129,12 +132,12 @@ fn asin64(x: f64) -> f64 {...@@ -129,12 +132,12 @@ fn asin64(x: f64) -> f64 {
129 }132 }
130}133}
131134
132test "asin" {135test "math.asin" {
133 assert(asin(f32(0.0)) == asin32(0.0));136 assert(asin_workaround(f32(0.0)) == asin32(0.0));
134 assert(asin(f64(0.0)) == asin64(0.0));137 assert(asin_workaround(f64(0.0)) == asin64(0.0));
135}138}
136139
137test "asin32" {140test "math.asin32" {
138 const epsilon = 0.000001;141 const epsilon = 0.000001;
139142
140 assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon));143 assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
...@@ -145,7 +148,7 @@ test "asin32" {...@@ -145,7 +148,7 @@ test "asin32" {
145 assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));148 assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
146}149}
147150
148test "asin64" {151test "math.asin64" {
149 const epsilon = 0.000001;152 const epsilon = 0.000001;
150153
151 assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon));154 assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
std/math/asinh.zig+27-24
...@@ -1,17 +1,20 @@...@@ -1,17 +1,20 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn asinh(x: var) -> @typeOf(x) {4pub const asinh = asinh_workaround;
5
6// TODO issue #393
7pub fn asinh_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(asinhf, x),10 f32 => @inlineCall(asinh32, x),
8 f64 => @inlineCall(asinhd, x),11 f64 => @inlineCall(asinh64, x),
9 else => @compileError("asinh not implemented for " ++ @typeName(T)),12 else => @compileError("asinh not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13// asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5)16// asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5)
14fn asinhf(x: f32) -> f32 {17fn asinh32(x: f32) -> f32 {
15 const u = @bitCast(u32, x);18 const u = @bitCast(u32, x);
16 const i = u & 0x7FFFFFFF;19 const i = u & 0x7FFFFFFF;
17 const s = i >> 31;20 const s = i >> 31;
...@@ -38,7 +41,7 @@ fn asinhf(x: f32) -> f32 {...@@ -38,7 +41,7 @@ fn asinhf(x: f32) -> f32 {
38 if (s != 0) -rx else rx41 if (s != 0) -rx else rx
39}42}
4043
41fn asinhd(x: f64) -> f64 {44fn asinh64(x: f64) -> f64 {
42 const u = @bitCast(u64, x);45 const u = @bitCast(u64, x);
43 const e = (u >> 52) & 0x7FF;46 const e = (u >> 52) & 0x7FF;
44 const s = u >> 63;47 const s = u >> 63;
...@@ -65,31 +68,31 @@ fn asinhd(x: f64) -> f64 {...@@ -65,31 +68,31 @@ fn asinhd(x: f64) -> f64 {
65 if (s != 0) -rx else rx68 if (s != 0) -rx else rx
66}69}
6770
68test "asinh" {71test "math.asinh" {
69 assert(asinh(f32(0.0)) == asinhf(0.0));72 assert(asinh_workaround(f32(0.0)) == asinh32(0.0));
70 assert(asinh(f64(0.0)) == asinhd(0.0));73 assert(asinh_workaround(f64(0.0)) == asinh64(0.0));
71}74}
7275
73test "asinhf" {76test "math.asinh32" {
74 const epsilon = 0.000001;77 const epsilon = 0.000001;
7578
76 assert(math.approxEq(f32, asinhf(0.0), 0.0, epsilon));79 assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
77 assert(math.approxEq(f32, asinhf(0.2), 0.198690, epsilon));80 assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
78 assert(math.approxEq(f32, asinhf(0.8923), 0.803133, epsilon));81 assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
79 assert(math.approxEq(f32, asinhf(1.5), 1.194763, epsilon));82 assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
80 assert(math.approxEq(f32, asinhf(37.45), 4.316332, epsilon));83 assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
81 assert(math.approxEq(f32, asinhf(89.123), 5.183196, epsilon));84 assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
82 assert(math.approxEq(f32, asinhf(123123.234375), 12.414088, epsilon));85 assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
83}86}
8487
85test "asinhd" {88test "math.asinh64" {
86 const epsilon = 0.000001;89 const epsilon = 0.000001;
8790
88 assert(math.approxEq(f64, asinhd(0.0), 0.0, epsilon));91 assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
89 assert(math.approxEq(f64, asinhd(0.2), 0.198690, epsilon));92 assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
90 assert(math.approxEq(f64, asinhd(0.8923), 0.803133, epsilon));93 assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
91 assert(math.approxEq(f64, asinhd(1.5), 1.194763, epsilon));94 assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
92 assert(math.approxEq(f64, asinhd(37.45), 4.316332, epsilon));95 assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
93 assert(math.approxEq(f64, asinhd(89.123), 5.183196, epsilon));96 assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
94 assert(math.approxEq(f64, asinhd(123123.234375), 12.414088, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn atan(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const atan = atan_workaround;
6
7pub fn atan_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(atan32, x),10 f32 => @inlineCall(atan32, x),
...@@ -201,12 +204,12 @@ fn atan64(x_: f64) -> f64 {...@@ -201,12 +204,12 @@ fn atan64(x_: f64) -> f64 {
201 }204 }
202}205}
203206
204test "atan" {207test "math.atan" {
205 assert(atan(f32(0.2)) == atan32(0.2));208 assert(atan_workaround(f32(0.2)) == atan32(0.2));
206 assert(atan(f64(0.2)) == atan64(0.2));209 assert(atan_workaround(f64(0.2)) == atan64(0.2));
207}210}
208211
209test "atan32" {212test "math.atan32" {
210 const epsilon = 0.000001;213 const epsilon = 0.000001;
211214
212 assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));215 assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
...@@ -216,7 +219,7 @@ test "atan32" {...@@ -216,7 +219,7 @@ test "atan32" {
216 assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));219 assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
217}220}
218221
219test "atan64" {222test "math.atan64" {
220 const epsilon = 0.000001;223 const epsilon = 0.000001;
221224
222 assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));225 assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
std/math/atan2.zig+27-24
...@@ -1,15 +1,18 @@...@@ -1,15 +1,18 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn atan2(comptime T: type, x: T, y: T) -> T {4pub const atan2 = atan2_workaround;
5
6// TODO issue #393
7pub fn atan2_workaround(comptime T: type, x: T, y: T) -> T {
5 switch (T) {8 switch (T) {
6 f32 => @inlineCall(atan2f, x, y),9 f32 => @inlineCall(atan2_32, x, y),
7 f64 => @inlineCall(atan2d, x, y),10 f64 => @inlineCall(atan2_64, x, y),
8 else => @compileError("atan2 not implemented for " ++ @typeName(T)),11 else => @compileError("atan2 not implemented for " ++ @typeName(T)),
9 }12 }
10}13}
1114
12fn atan2f(y: f32, x: f32) -> f32 {15fn atan2_32(y: f32, x: f32) -> f32 {
13 const pi: f32 = 3.1415927410e+00;16 const pi: f32 = 3.1415927410e+00;
14 const pi_lo: f32 = -8.7422776573e-08;17 const pi_lo: f32 = -8.7422776573e-08;
1518
...@@ -94,7 +97,7 @@ fn atan2f(y: f32, x: f32) -> f32 {...@@ -94,7 +97,7 @@ fn atan2f(y: f32, x: f32) -> f32 {
94 }97 }
95}98}
9699
97fn atan2d(y: f64, x: f64) -> f64 {100fn atan2_64(y: f64, x: f64) -> f64 {
98 const pi: f64 = 3.1415926535897931160E+00;101 const pi: f64 = 3.1415926535897931160E+00;
99 const pi_lo: f64 = 1.2246467991473531772E-16;102 const pi_lo: f64 = 1.2246467991473531772E-16;
100103
...@@ -184,31 +187,31 @@ fn atan2d(y: f64, x: f64) -> f64 {...@@ -184,31 +187,31 @@ fn atan2d(y: f64, x: f64) -> f64 {
184 }187 }
185}188}
186189
187test "atan2" {190test "math.atan2" {
188 assert(atan2(f32, 0.2, 0.21) == atan2f(0.2, 0.21));191 assert(atan2_workaround(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));
189 assert(atan2(f64, 0.2, 0.21) == atan2d(0.2, 0.21));192 assert(atan2_workaround(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));
190}193}
191194
192test "atan2f" {195test "math.atan2_32" {
193 const epsilon = 0.000001;196 const epsilon = 0.000001;
194197
195 assert(math.approxEq(f32, atan2f(0.0, 0.0), 0.0, epsilon));198 assert(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));
196 assert(math.approxEq(f32, atan2f(0.2, 0.2), 0.785398, epsilon));199 assert(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon));
197 assert(math.approxEq(f32, atan2f(-0.2, 0.2), -0.785398, epsilon));200 assert(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon));
198 assert(math.approxEq(f32, atan2f(0.2, -0.2), 2.356194, epsilon));201 assert(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon));
199 assert(math.approxEq(f32, atan2f(-0.2, -0.2), -2.356194, epsilon));202 assert(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon));
200 assert(math.approxEq(f32, atan2f(0.34, -0.4), 2.437099, epsilon));203 assert(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));
201 assert(math.approxEq(f32, atan2f(0.34, 1.243), 0.267001, epsilon));204 assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
202}205}
203206
204test "atan2d" {207test "math.atan2_64" {
205 const epsilon = 0.000001;208 const epsilon = 0.000001;
206209
207 assert(math.approxEq(f64, atan2d(0.0, 0.0), 0.0, epsilon));210 assert(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));
208 assert(math.approxEq(f64, atan2d(0.2, 0.2), 0.785398, epsilon));211 assert(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon));
209 assert(math.approxEq(f64, atan2d(-0.2, 0.2), -0.785398, epsilon));212 assert(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon));
210 assert(math.approxEq(f64, atan2d(0.2, -0.2), 2.356194, epsilon));213 assert(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon));
211 assert(math.approxEq(f64, atan2d(-0.2, -0.2), -2.356194, epsilon));214 assert(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon));
212 assert(math.approxEq(f64, atan2d(0.34, -0.4), 2.437099, epsilon));215 assert(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));
213 assert(math.approxEq(f64, atan2d(0.34, 1.243), 0.267001, 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,17 +1,20 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn atanh(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const atanh = atanh_workaround;
6
7pub fn atanh_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(atanhf, x),10 f32 => @inlineCall(atanh_32, x),
8 f64 => @inlineCall(atanhd, x),11 f64 => @inlineCall(atanh_64, x),
9 else => @compileError("atanh not implemented for " ++ @typeName(T)),12 else => @compileError("atanh not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13// atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5)16// atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5)
14fn atanhf(x: f32) -> f32 {17fn atanh_32(x: f32) -> f32 {
15 const u = @bitCast(u32, x);18 const u = @bitCast(u32, x);
16 const i = u & 0x7FFFFFFF;19 const i = u & 0x7FFFFFFF;
17 const s = u >> 31;20 const s = u >> 31;
...@@ -37,7 +40,7 @@ fn atanhf(x: f32) -> f32 {...@@ -37,7 +40,7 @@ fn atanhf(x: f32) -> f32 {
37 if (s != 0) -y else y40 if (s != 0) -y else y
38}41}
3942
40fn atanhd(x: f64) -> f64 {43fn atanh_64(x: f64) -> f64 {
41 const u = @bitCast(u64, x);44 const u = @bitCast(u64, x);
42 const e = (u >> 52) & 0x7FF;45 const e = (u >> 52) & 0x7FF;
43 const s = u >> 63;46 const s = u >> 63;
...@@ -63,23 +66,23 @@ fn atanhd(x: f64) -> f64 {...@@ -63,23 +66,23 @@ fn atanhd(x: f64) -> f64 {
63 if (s != 0) -y else y66 if (s != 0) -y else y
64}67}
6568
66test "atanh" {69test "math.atanh" {
67 assert(atanh(f32(0.0)) == atanhf(0.0));70 assert(atanh(f32(0.0)) == atanh_32(0.0));
68 assert(atanh(f64(0.0)) == atanhd(0.0));71 assert(atanh(f64(0.0)) == atanh_64(0.0));
69}72}
7073
71test "atanhf" {74test "math.atanh_32" {
72 const epsilon = 0.000001;75 const epsilon = 0.000001;
7376
74 assert(math.approxEq(f32, atanhf(0.0), 0.0, epsilon));77 assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
75 assert(math.approxEq(f32, atanhf(0.2), 0.202733, epsilon));78 assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
76 assert(math.approxEq(f32, atanhf(0.8923), 1.433099, epsilon));79 assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
77}80}
7881
79test "atanhd" {82test "math.atanh_64" {
80 const epsilon = 0.000001;83 const epsilon = 0.000001;
8184
82 assert(math.approxEq(f64, atanhd(0.0), 0.0, epsilon));85 assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
83 assert(math.approxEq(f64, atanhd(0.2), 0.202733, epsilon));86 assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
84 assert(math.approxEq(f64, atanhd(0.8923), 1.433099, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn cbrt(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const cbrt = cbrt_workaround;
6
7pub fn cbrt_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(cbrt32, x),10 f32 => @inlineCall(cbrt32, x),
...@@ -106,12 +109,12 @@ fn cbrt64(x: f64) -> f64 {...@@ -106,12 +109,12 @@ fn cbrt64(x: f64) -> f64 {
106 t + t * q109 t + t * q
107}110}
108111
109test "cbrt" {112test "math.cbrt" {
110 assert(cbrt(f32(0.0)) == cbrt32(0.0));113 assert(cbrt(f32(0.0)) == cbrt32(0.0));
111 assert(cbrt(f64(0.0)) == cbrt64(0.0));114 assert(cbrt(f64(0.0)) == cbrt64(0.0));
112}115}
113116
114test "cbrt32" {117test "math.cbrt32" {
115 const epsilon = 0.000001;118 const epsilon = 0.000001;
116119
117 assert(cbrt32(0.0) == 0.0);120 assert(cbrt32(0.0) == 0.0);
...@@ -122,7 +125,7 @@ test "cbrt32" {...@@ -122,7 +125,7 @@ test "cbrt32" {
122 assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));125 assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
123}126}
124127
125test "cbrt64" {128test "math.cbrt64" {
126 const epsilon = 0.000001;129 const epsilon = 0.000001;
127130
128 assert(cbrt64(0.0) == 0.0);131 assert(cbrt64(0.0) == 0.0);
std/math/ceil.zig+7-4
...@@ -2,7 +2,10 @@ const builtin = @import("builtin");...@@ -2,7 +2,10 @@ const builtin = @import("builtin");
2const math = @import("index.zig");2const math = @import("index.zig");
3const assert = @import("../debug.zig").assert;3const assert = @import("../debug.zig").assert;
44
5pub fn ceil(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const ceil = ceil_workaround;
7
8pub fn ceil_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(ceil32, x),11 f32 => @inlineCall(ceil32, x),
...@@ -71,18 +74,18 @@ fn ceil64(x: f64) -> f64 {...@@ -71,18 +74,18 @@ fn ceil64(x: f64) -> f64 {
71 }74 }
72}75}
7376
74test "ceil" {77test "math.ceil" {
75 assert(ceil(f32(0.0)) == ceil32(0.0));78 assert(ceil(f32(0.0)) == ceil32(0.0));
76 assert(ceil(f64(0.0)) == ceil64(0.0));79 assert(ceil(f64(0.0)) == ceil64(0.0));
77}80}
7881
79test "ceil32" {82test "math.ceil32" {
80 assert(ceil32(1.3) == 2.0);83 assert(ceil32(1.3) == 2.0);
81 assert(ceil32(-1.3) == -1.0);84 assert(ceil32(-1.3) == -1.0);
82 assert(ceil32(0.2) == 1.0);85 assert(ceil32(0.2) == 1.0);
83}86}
8487
85test "ceil64" {88test "math.ceil64" {
86 assert(ceil64(1.3) == 2.0);89 assert(ceil64(1.3) == 2.0);
87 assert(ceil64(-1.3) == -1.0);90 assert(ceil64(-1.3) == -1.0);
88 assert(ceil64(0.2) == 1.0);91 assert(ceil64(0.2) == 1.0);
std/math/copysign.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn copysign(comptime T: type, x: T, y: T) -> T {4// TODO issue #393
5pub const copysign = copysign_workaround;
6
7pub fn copysign_workaround(comptime T: type, x: T, y: T) -> T {
5 switch (T) {8 switch (T) {
6 f32 => @inlineCall(copysign32, x, y),9 f32 => @inlineCall(copysign32, x, y),
7 f64 => @inlineCall(copysign64, x, y),10 f64 => @inlineCall(copysign64, x, y),
...@@ -27,19 +30,19 @@ fn copysign64(x: f64, y: f64) -> f64 {...@@ -27,19 +30,19 @@ fn copysign64(x: f64, y: f64) -> f64 {
27 @bitCast(f64, h1 | h2)30 @bitCast(f64, h1 | h2)
28}31}
2932
30test "copysign" {33test "math.copysign" {
31 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));34 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
32 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));35 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
33}36}
3437
35test "copysign32" {38test "math.copysign32" {
36 assert(copysign32(5.0, 1.0) == 5.0);39 assert(copysign32(5.0, 1.0) == 5.0);
37 assert(copysign32(5.0, -1.0) == -5.0);40 assert(copysign32(5.0, -1.0) == -5.0);
38 assert(copysign32(-5.0, -1.0) == -5.0);41 assert(copysign32(-5.0, -1.0) == -5.0);
39 assert(copysign32(-5.0, 1.0) == 5.0);42 assert(copysign32(-5.0, 1.0) == 5.0);
40}43}
4144
42test "copysign64" {45test "math.copysign64" {
43 assert(copysign64(5.0, 1.0) == 5.0);46 assert(copysign64(5.0, 1.0) == 5.0);
44 assert(copysign64(5.0, -1.0) == -5.0);47 assert(copysign64(5.0, -1.0) == -5.0);
45 assert(copysign64(-5.0, -1.0) == -5.0);48 assert(copysign64(-5.0, -1.0) == -5.0);
std/math/cos.zig+8-4
...@@ -1,7 +1,11 @@...@@ -1,7 +1,11 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn cos(x: var) -> @typeOf(x) {4
5// TODO issue #393
6pub const cos = cos_workaround;
7
8pub fn cos_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);9 const T = @typeOf(x);
6 switch (T) {10 switch (T) {
7 f32 => @inlineCall(cos32, x),11 f32 => @inlineCall(cos32, x),
...@@ -133,12 +137,12 @@ fn cos64(x_: f64) -> f64 {...@@ -133,12 +137,12 @@ fn cos64(x_: f64) -> f64 {
133 }137 }
134}138}
135139
136test "cos" {140test "math.cos" {
137 assert(cos(f32(0.0)) == cos32(0.0));141 assert(cos(f32(0.0)) == cos32(0.0));
138 assert(cos(f64(0.0)) == cos64(0.0));142 assert(cos(f64(0.0)) == cos64(0.0));
139}143}
140144
141test "cos32" {145test "math.cos32" {
142 const epsilon = 0.000001;146 const epsilon = 0.000001;
143147
144 assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon));148 assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
...@@ -149,7 +153,7 @@ test "cos32" {...@@ -149,7 +153,7 @@ test "cos32" {
149 assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));153 assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
150}154}
151155
152test "cos64" {156test "math.cos64" {
153 const epsilon = 0.000001;157 const epsilon = 0.000001;
154158
155 assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon));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,11 +2,14 @@ const math = @import("index.zig");
2const expo2 = @import("_expo2.zig").expo2;2const expo2 = @import("_expo2.zig").expo2;
3const assert = @import("../debug.zig").assert;3const assert = @import("../debug.zig").assert;
44
5pub fn cosh(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const cosh = cosh_workaround;
7
8pub fn cosh_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(coshf, x),11 f32 => @inlineCall(cosh32, x),
9 f64 => @inlineCall(coshd, x),12 f64 => @inlineCall(cosh64, x),
10 else => @compileError("cosh not implemented for " ++ @typeName(T)),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,7 +17,7 @@ pub fn cosh(x: var) -> @typeOf(x) {
14// cosh(x) = (exp(x) + 1 / exp(x)) / 217// cosh(x) = (exp(x) + 1 / exp(x)) / 2
15// = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x)18// = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x)
16// = 1 + (x * x) / 2 + o(x^4)19// = 1 + (x * x) / 2 + o(x^4)
17fn coshf(x: f32) -> f32 {20fn cosh32(x: f32) -> f32 {
18 const u = @bitCast(u32, x);21 const u = @bitCast(u32, x);
19 const ux = u & 0x7FFFFFFF;22 const ux = u & 0x7FFFFFFF;
20 const ax = @bitCast(f32, ux);23 const ax = @bitCast(f32, ux);
...@@ -39,7 +42,7 @@ fn coshf(x: f32) -> f32 {...@@ -39,7 +42,7 @@ fn coshf(x: f32) -> f32 {
39 expo2(ax)42 expo2(ax)
40}43}
4144
42fn coshd(x: f64) -> f64 {45fn cosh64(x: f64) -> f64 {
43 const u = @bitCast(u64, x);46 const u = @bitCast(u64, x);
44 const w = u32(u >> 32);47 const w = u32(u >> 32);
45 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));48 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
...@@ -67,25 +70,25 @@ fn coshd(x: f64) -> f64 {...@@ -67,25 +70,25 @@ fn coshd(x: f64) -> f64 {
67 expo2(ax)70 expo2(ax)
68}71}
6972
70test "cosh" {73test "math.cosh" {
71 assert(cosh(f32(1.5)) == coshf(1.5));74 assert(cosh(f32(1.5)) == cosh32(1.5));
72 assert(cosh(f64(1.5)) == coshd(1.5));75 assert(cosh(f64(1.5)) == cosh64(1.5));
73}76}
7477
75test "coshf" {78test "math.cosh32" {
76 const epsilon = 0.000001;79 const epsilon = 0.000001;
7780
78 assert(math.approxEq(f32, coshf(0.0), 1.0, epsilon));81 assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
79 assert(math.approxEq(f32, coshf(0.2), 1.020067, epsilon));82 assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
80 assert(math.approxEq(f32, coshf(0.8923), 1.425225, epsilon));83 assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
81 assert(math.approxEq(f32, coshf(1.5), 2.352410, epsilon));84 assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
82}85}
8386
84test "coshd" {87test "math.cosh64" {
85 const epsilon = 0.000001;88 const epsilon = 0.000001;
8689
87 assert(math.approxEq(f64, coshd(0.0), 1.0, epsilon));90 assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
88 assert(math.approxEq(f64, coshd(0.2), 1.020067, epsilon));91 assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
89 assert(math.approxEq(f64, coshd(0.8923), 1.425225, epsilon));92 assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
90 assert(math.approxEq(f64, coshd(1.5), 2.352410, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn exp(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const exp = exp_workaround;
6
7pub fn exp_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(exp32, x),10 f32 => @inlineCall(exp32, x),
...@@ -165,12 +168,12 @@ fn exp64(x_: f64) -> f64 {...@@ -165,12 +168,12 @@ fn exp64(x_: f64) -> f64 {
165 }168 }
166}169}
167170
168test "exp" {171test "math.exp" {
169 assert(exp(f32(0.0)) == exp32(0.0));172 assert(exp(f32(0.0)) == exp32(0.0));
170 assert(exp(f64(0.0)) == exp64(0.0));173 assert(exp(f64(0.0)) == exp64(0.0));
171}174}
172175
173test "exp32" {176test "math.exp32" {
174 const epsilon = 0.000001;177 const epsilon = 0.000001;
175178
176 assert(exp32(0.0) == 1.0);179 assert(exp32(0.0) == 1.0);
...@@ -180,7 +183,7 @@ test "exp32" {...@@ -180,7 +183,7 @@ test "exp32" {
180 assert(math.approxEq(f32, exp32(1.5), 4.481689, epsilon));183 assert(math.approxEq(f32, exp32(1.5), 4.481689, epsilon));
181}184}
182185
183test "exp64" {186test "math.exp64" {
184 const epsilon = 0.000001;187 const epsilon = 0.000001;
185188
186 assert(exp64(0.0) == 1.0);189 assert(exp64(0.0) == 1.0);
std/math/exp2.zig+23-20
...@@ -1,11 +1,14 @@...@@ -1,11 +1,14 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn exp2(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const exp2 = exp2_workaround;
6
7pub fn exp2_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(exp2f, x),10 f32 => @inlineCall(exp2_32, x),
8 f64 => @inlineCall(exp2d, x),11 f64 => @inlineCall(exp2_64, x),
9 else => @compileError("exp2 not implemented for " ++ @typeName(T)),12 else => @compileError("exp2 not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
...@@ -29,7 +32,7 @@ const exp2ft = []const f64 {...@@ -29,7 +32,7 @@ const exp2ft = []const f64 {
29 0x1.5ab07dd485429p+0,32 0x1.5ab07dd485429p+0,
30};33};
3134
32fn exp2f(x: f32) -> f32 {35fn exp2_32(x: f32) -> f32 {
33 @setFloatMode(this, @import("builtin").FloatMode.Strict);36 @setFloatMode(this, @import("builtin").FloatMode.Strict);
3437
35 const tblsiz = u32(exp2ft.len);38 const tblsiz = u32(exp2ft.len);
...@@ -346,7 +349,7 @@ const exp2dt = []f64 {...@@ -346,7 +349,7 @@ const exp2dt = []f64 {
346 0x1.690f4b19e9471p+0, -0x1.9780p-45,349 0x1.690f4b19e9471p+0, -0x1.9780p-45,
347};350};
348351
349fn exp2d(x: f64) -> f64 {352fn exp2_64(x: f64) -> f64 {
350 @setFloatMode(this, @import("builtin").FloatMode.Strict);353 @setFloatMode(this, @import("builtin").FloatMode.Strict);
351354
352 const tblsiz = u32(exp2dt.len / 2);355 const tblsiz = u32(exp2dt.len / 2);
...@@ -407,27 +410,27 @@ fn exp2d(x: f64) -> f64 {...@@ -407,27 +410,27 @@ fn exp2d(x: f64) -> f64 {
407 math.scalbn(r, ik)410 math.scalbn(r, ik)
408}411}
409412
410test "exp2" {413test "math.exp2" {
411 assert(exp2(f32(0.8923)) == exp2f(0.8923));414 assert(exp2(f32(0.8923)) == exp2_32(0.8923));
412 assert(exp2(f64(0.8923)) == exp2d(0.8923));415 assert(exp2(f64(0.8923)) == exp2_64(0.8923));
413}416}
414417
415test "exp2f" {418test "math.exp2_32" {
416 const epsilon = 0.000001;419 const epsilon = 0.000001;
417420
418 assert(exp2f(0.0) == 1.0);421 assert(exp2_32(0.0) == 1.0);
419 assert(math.approxEq(f32, exp2f(0.2), 1.148698, epsilon));422 assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
420 assert(math.approxEq(f32, exp2f(0.8923), 1.856133, epsilon));423 assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
421 assert(math.approxEq(f32, exp2f(1.5), 2.828427, epsilon));424 assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
422 assert(math.approxEq(f32, exp2f(37.45), 187747237888, epsilon));425 assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
423}426}
424427
425test "exp2d" {428test "math.exp2_64" {
426 const epsilon = 0.000001;429 const epsilon = 0.000001;
427430
428 assert(exp2d(0.0) == 1.0);431 assert(exp2_64(0.0) == 1.0);
429 assert(math.approxEq(f64, exp2d(0.2), 1.148698, epsilon));432 assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
430 assert(math.approxEq(f64, exp2d(0.8923), 1.856133, epsilon));433 assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
431 assert(math.approxEq(f64, exp2d(1.5), 2.828427, epsilon));434 assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
432 // assert(math.approxEq(f64, exp2d(37.45), 18379273786760560.000000, 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,16 +1,19 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn expm1(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const expm1 = expm1_workaround;
6
7pub fn expm1_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(expm1f, x),10 f32 => @inlineCall(expm1_32, x),
8 f64 => @inlineCall(expm1d, x),11 f64 => @inlineCall(expm1_64, x),
9 else => @compileError("exp1m not implemented for " ++ @typeName(T)),12 else => @compileError("exp1m not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13fn expm1f(x_: f32) -> f32 {16fn expm1_32(x_: f32) -> f32 {
14 const o_threshold: f32 = 8.8721679688e+01;17 const o_threshold: f32 = 8.8721679688e+01;
15 const ln2_hi: f32 = 6.9313812256e-01;18 const ln2_hi: f32 = 6.9313812256e-01;
16 const ln2_lo: f32 = 9.0580006145e-06;19 const ln2_lo: f32 = 9.0580006145e-06;
...@@ -131,7 +134,7 @@ fn expm1f(x_: f32) -> f32 {...@@ -131,7 +134,7 @@ fn expm1f(x_: f32) -> f32 {
131 }134 }
132}135}
133136
134fn expm1d(x_: f64) -> f64 {137fn expm1_64(x_: f64) -> f64 {
135 const o_threshold: f64 = 7.09782712893383973096e+02;138 const o_threshold: f64 = 7.09782712893383973096e+02;
136 const ln2_hi: f64 = 6.93147180369123816490e-01;139 const ln2_hi: f64 = 6.93147180369123816490e-01;
137 const ln2_lo: f64 = 1.90821492927058770002e-10;140 const ln2_lo: f64 = 1.90821492927058770002e-10;
...@@ -256,27 +259,27 @@ fn expm1d(x_: f64) -> f64 {...@@ -256,27 +259,27 @@ fn expm1d(x_: f64) -> f64 {
256 }259 }
257}260}
258261
259test "exp1m" {262test "math.exp1m" {
260 assert(expm1(f32(0.0)) == expm1f(0.0));263 assert(expm1(f32(0.0)) == expm1_32(0.0));
261 assert(expm1(f64(0.0)) == expm1d(0.0));264 assert(expm1(f64(0.0)) == expm1_64(0.0));
262}265}
263266
264test "expm1f" {267test "math.expm1_32" {
265 const epsilon = 0.000001;268 const epsilon = 0.000001;
266269
267 assert(expm1f(0.0) == 0.0);270 assert(expm1_32(0.0) == 0.0);
268 assert(math.approxEq(f32, expm1f(0.0), 0.0, epsilon));271 assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
269 assert(math.approxEq(f32, expm1f(0.2), 0.221403, epsilon));272 assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
270 assert(math.approxEq(f32, expm1f(0.8923), 1.440737, epsilon));273 assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
271 assert(math.approxEq(f32, expm1f(1.5), 3.481689, epsilon));274 assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
272}275}
273276
274test "expm1d" {277test "math.expm1_64" {
275 const epsilon = 0.000001;278 const epsilon = 0.000001;
276279
277 assert(expm1d(0.0) == 0.0);280 assert(expm1_64(0.0) == 0.0);
278 assert(math.approxEq(f64, expm1d(0.0), 0.0, epsilon));281 assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
279 assert(math.approxEq(f64, expm1d(0.2), 0.221403, epsilon));282 assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
280 assert(math.approxEq(f64, expm1d(0.8923), 1.440737, epsilon));283 assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
281 assert(math.approxEq(f64, expm1d(1.5), 3.481689, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn fabs(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const fabs = fabs_workaround;
6
7pub fn fabs_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(fabs32, x),10 f32 => @inlineCall(fabs32, x),
...@@ -22,17 +25,17 @@ fn fabs64(x: f64) -> f64 {...@@ -22,17 +25,17 @@ fn fabs64(x: f64) -> f64 {
22 @bitCast(f64, u)25 @bitCast(f64, u)
23}26}
2427
25test "fabs" {28test "math.fabs" {
26 assert(fabs(f32(1.0)) == fabs32(1.0));29 assert(fabs(f32(1.0)) == fabs32(1.0));
27 assert(fabs(f64(1.0)) == fabs64(1.0));30 assert(fabs(f64(1.0)) == fabs64(1.0));
28}31}
2932
30test "fabs32" {33test "math.fabs32" {
31 assert(fabs64(1.0) == 1.0);34 assert(fabs64(1.0) == 1.0);
32 assert(fabs64(-1.0) == 1.0);35 assert(fabs64(-1.0) == 1.0);
33}36}
3437
35test "fabs64" {38test "math.fabs64" {
36 assert(fabs64(1.0) == 1.0);39 assert(fabs64(1.0) == 1.0);
37 assert(fabs64(-1.0) == 1.0);40 assert(fabs64(-1.0) == 1.0);
38}41}
std/math/floor.zig+7-4
...@@ -2,7 +2,10 @@ const builtin = @import("builtin");...@@ -2,7 +2,10 @@ const builtin = @import("builtin");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
3const math = @import("index.zig");3const math = @import("index.zig");
44
5pub fn floor(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const floor = floor_workaround;
7
8pub fn floor_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(floor32, x),11 f32 => @inlineCall(floor32, x),
...@@ -71,18 +74,18 @@ fn floor64(x: f64) -> f64 {...@@ -71,18 +74,18 @@ fn floor64(x: f64) -> f64 {
71 }74 }
72}75}
7376
74test "floor" {77test "math.floor" {
75 assert(floor(f32(1.3)) == floor32(1.3));78 assert(floor(f32(1.3)) == floor32(1.3));
76 assert(floor(f64(1.3)) == floor64(1.3));79 assert(floor(f64(1.3)) == floor64(1.3));
77}80}
7881
79test "floor32" {82test "math.floor32" {
80 assert(floor32(1.3) == 1.0);83 assert(floor32(1.3) == 1.0);
81 assert(floor32(-1.3) == -2.0);84 assert(floor32(-1.3) == -2.0);
82 assert(floor32(0.2) == 0.0);85 assert(floor32(0.2) == 0.0);
83}86}
8487
85test "floor64" {88test "math.floor64" {
86 assert(floor64(1.3) == 1.0);89 assert(floor64(1.3) == 1.0);
87 assert(floor64(-1.3) == -2.0);90 assert(floor64(-1.3) == -2.0);
88 assert(floor64(0.2) == 0.0);91 assert(floor64(0.2) == 0.0);
std/math/fma.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn fma(comptime T: type, x: T, y: T, z: T) -> T {4// TODO issue #393
5pub const fma = fma_workaround;
6
7pub fn fma_workaround(comptime T: type, x: T, y: T, z: T) -> T {
5 switch (T) {8 switch (T) {
6 f32 => @inlineCall(fma32, x, y, z),9 f32 => @inlineCall(fma32, x, y, z),
7 f64 => @inlineCall(fma64, x, y ,z),10 f64 => @inlineCall(fma64, x, y ,z),
...@@ -130,12 +133,12 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 {...@@ -130,12 +133,12 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 {
130 math.scalbn(sum.hi, scale)133 math.scalbn(sum.hi, scale)
131}134}
132135
133test "fma" {136test "math.fma" {
134 assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));137 assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));
135 assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));138 assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));
136}139}
137140
138test "fma32" {141test "math.fma32" {
139 const epsilon = 0.000001;142 const epsilon = 0.000001;
140143
141 assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));144 assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));
...@@ -147,7 +150,7 @@ test "fma32" {...@@ -147,7 +150,7 @@ test "fma32" {
147 assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));150 assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
148}151}
149152
150test "fma64" {153test "math.fma64" {
151 const epsilon = 0.000001;154 const epsilon = 0.000001;
152155
153 assert(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));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 @@
1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;
3
4pub 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
12fn 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
90fn 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
169test "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
174test "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
183test "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,6 +1,9 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4// TODO issue #393
5pub const frexp = frexp_workaround;
6
4fn frexp_result(comptime T: type) -> type {7fn frexp_result(comptime T: type) -> type {
5 struct {8 struct {
6 significand: T,9 significand: T,
...@@ -10,7 +13,7 @@ fn frexp_result(comptime T: type) -> type {...@@ -10,7 +13,7 @@ fn frexp_result(comptime T: type) -> type {
10pub const frexp32_result = frexp_result(f32);13pub const frexp32_result = frexp_result(f32);
11pub const frexp64_result = frexp_result(f64);14pub const frexp64_result = frexp_result(f64);
1215
13pub fn frexp(x: var) -> frexp_result(@typeOf(x)) {16pub fn frexp_workaround(x: var) -> frexp_result(@typeOf(x)) {
14 const T = @typeOf(x);17 const T = @typeOf(x);
15 switch (T) {18 switch (T) {
16 f32 => @inlineCall(frexp32, x),19 f32 => @inlineCall(frexp32, x),
...@@ -80,7 +83,7 @@ fn frexp64(x: f64) -> frexp64_result {...@@ -80,7 +83,7 @@ fn frexp64(x: f64) -> frexp64_result {
80 result83 result
81}84}
8285
83test "frexp" {86test "math.frexp" {
84 const a = frexp(f32(1.3));87 const a = frexp(f32(1.3));
85 const b = frexp32(1.3);88 const b = frexp32(1.3);
86 assert(a.significand == b.significand and a.exponent == b.exponent);89 assert(a.significand == b.significand and a.exponent == b.exponent);
...@@ -90,7 +93,7 @@ test "frexp" {...@@ -90,7 +93,7 @@ test "frexp" {
90 assert(c.significand == d.significand and c.exponent == d.exponent);93 assert(c.significand == d.significand and c.exponent == d.exponent);
91}94}
9295
93test "frexp32" {96test "math.frexp32" {
94 const epsilon = 0.000001;97 const epsilon = 0.000001;
95 var r: frexp32_result = undefined;98 var r: frexp32_result = undefined;
9699
...@@ -101,7 +104,7 @@ test "frexp32" {...@@ -101,7 +104,7 @@ test "frexp32" {
101 assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);104 assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);
102}105}
103106
104test "frexp64" {107test "math.frexp64" {
105 const epsilon = 0.000001;108 const epsilon = 0.000001;
106 var r: frexp64_result = undefined;109 var r: frexp64_result = undefined;
107110
std/math/hypot.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn hypot(comptime T: type, x: T, y: T) -> T {4// TODO issue #393
5pub const hypot = hypot_workaround;
6
7pub fn hypot_workaround(comptime T: type, x: T, y: T) -> T {
5 switch (T) {8 switch (T) {
6 f32 => @inlineCall(hypot32, x, y),9 f32 => @inlineCall(hypot32, x, y),
7 f64 => @inlineCall(hypot64, x, y),10 f64 => @inlineCall(hypot64, x, y),
...@@ -105,12 +108,12 @@ fn hypot64(x: f64, y: f64) -> f64 {...@@ -105,12 +108,12 @@ fn hypot64(x: f64, y: f64) -> f64 {
105 z * math.sqrt(ly + lx + hy + hx)108 z * math.sqrt(ly + lx + hy + hx)
106}109}
107110
108test "hypot" {111test "math.hypot" {
109 assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));112 assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
110 assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));113 assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
111}114}
112115
113test "hypot32" {116test "math.hypot32" {
114 const epsilon = 0.000001;117 const epsilon = 0.000001;
115118
116 assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));119 assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
...@@ -122,7 +125,7 @@ test "hypot32" {...@@ -122,7 +125,7 @@ test "hypot32" {
122 assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));125 assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
123}126}
124127
125test "hypot64" {128test "math.hypot64" {
126 const epsilon = 0.000001;129 const epsilon = 0.000001;
127130
128 assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));131 assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
std/math/ilogb.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn ilogb(x: var) -> i32 {4// TODO issue #393
5pub const ilogb = ilogb_workaround;
6
7pub fn ilogb_workaround(x: var) -> i32 {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(ilogb32, x),10 f32 => @inlineCall(ilogb32, x),
...@@ -76,12 +79,12 @@ fn ilogb64(x: f64) -> i32 {...@@ -76,12 +79,12 @@ fn ilogb64(x: f64) -> i32 {
76 e - 0x3FF79 e - 0x3FF
77}80}
7881
79test "ilogb" {82test "math.ilogb" {
80 assert(ilogb(f32(0.2)) == ilogb32(0.2));83 assert(ilogb(f32(0.2)) == ilogb32(0.2));
81 assert(ilogb(f64(0.2)) == ilogb64(0.2));84 assert(ilogb(f64(0.2)) == ilogb64(0.2));
82}85}
8386
84test "ilogb32" {87test "math.ilogb32" {
85 assert(ilogb32(0.0) == fp_ilogb0);88 assert(ilogb32(0.0) == fp_ilogb0);
86 assert(ilogb32(0.5) == -1);89 assert(ilogb32(0.5) == -1);
87 assert(ilogb32(0.8923) == -1);90 assert(ilogb32(0.8923) == -1);
...@@ -90,7 +93,7 @@ test "ilogb32" {...@@ -90,7 +93,7 @@ test "ilogb32" {
90 assert(ilogb32(2398.23) == 11);93 assert(ilogb32(2398.23) == 11);
91}94}
9295
93test "ilogb64" {96test "math.ilogb64" {
94 assert(ilogb64(0.0) == fp_ilogb0);97 assert(ilogb64(0.0) == fp_ilogb0);
95 assert(ilogb64(0.5) == -1);98 assert(ilogb64(0.5) == -1);
96 assert(ilogb64(0.8923) == -1);99 assert(ilogb64(0.8923) == -1);
std/math/index.zig-2
...@@ -98,7 +98,6 @@ pub const round = @import("round.zig").round;...@@ -98,7 +98,6 @@ pub const round = @import("round.zig").round;
98pub const frexp = @import("frexp.zig").frexp;98pub const frexp = @import("frexp.zig").frexp;
99pub const frexp32_result = @import("frexp.zig").frexp32_result;99pub const frexp32_result = @import("frexp.zig").frexp32_result;
100pub const frexp64_result = @import("frexp.zig").frexp64_result;100pub const frexp64_result = @import("frexp.zig").frexp64_result;
101pub const fmod = @import("fmod.zig").fmod;
102pub const modf = @import("modf.zig").modf;101pub const modf = @import("modf.zig").modf;
103pub const modf32_result = @import("modf.zig").modf32_result;102pub const modf32_result = @import("modf.zig").modf32_result;
104pub const modf64_result = @import("modf.zig").modf64_result;103pub const modf64_result = @import("modf.zig").modf64_result;
...@@ -147,7 +146,6 @@ test "math" {...@@ -147,7 +146,6 @@ test "math" {
147 _ = @import("trunc.zig");146 _ = @import("trunc.zig");
148 _ = @import("round.zig");147 _ = @import("round.zig");
149 _ = @import("frexp.zig");148 _ = @import("frexp.zig");
150 _ = @import("fmod.zig");
151 _ = @import("modf.zig");149 _ = @import("modf.zig");
152 _ = @import("copysign.zig");150 _ = @import("copysign.zig");
153 _ = @import("isfinite.zig");151 _ = @import("isfinite.zig");
std/math/isfinite.zig+1-1
...@@ -18,7 +18,7 @@ pub fn isFinite(x: var) -> bool {...@@ -18,7 +18,7 @@ pub fn isFinite(x: var) -> bool {
18 }18 }
19}19}
2020
21test "isFinite" {21test "math.isFinite" {
22 assert(isFinite(f32(0.0)));22 assert(isFinite(f32(0.0)));
23 assert(isFinite(f32(-0.0)));23 assert(isFinite(f32(-0.0)));
24 assert(isFinite(f64(0.0)));24 assert(isFinite(f64(0.0)));
std/math/isinf.zig+3-3
...@@ -48,7 +48,7 @@ pub fn isNegativeInf(x: var) -> bool {...@@ -48,7 +48,7 @@ pub fn isNegativeInf(x: var) -> bool {
48 }48 }
49}49}
5050
51test "isInf" {51test "math.isInf" {
52 assert(!isInf(f32(0.0)));52 assert(!isInf(f32(0.0)));
53 assert(!isInf(f32(-0.0)));53 assert(!isInf(f32(-0.0)));
54 assert(!isInf(f64(0.0)));54 assert(!isInf(f64(0.0)));
...@@ -59,7 +59,7 @@ test "isInf" {...@@ -59,7 +59,7 @@ test "isInf" {
59 assert(isInf(-math.inf(f64)));59 assert(isInf(-math.inf(f64)));
60}60}
6161
62test "isPositiveInf" {62test "math.isPositiveInf" {
63 assert(!isPositiveInf(f32(0.0)));63 assert(!isPositiveInf(f32(0.0)));
64 assert(!isPositiveInf(f32(-0.0)));64 assert(!isPositiveInf(f32(-0.0)));
65 assert(!isPositiveInf(f64(0.0)));65 assert(!isPositiveInf(f64(0.0)));
...@@ -70,7 +70,7 @@ test "isPositiveInf" {...@@ -70,7 +70,7 @@ test "isPositiveInf" {
70 assert(!isPositiveInf(-math.inf(f64)));70 assert(!isPositiveInf(-math.inf(f64)));
71}71}
7272
73test "isNegativeInf" {73test "math.isNegativeInf" {
74 assert(!isNegativeInf(f32(0.0)));74 assert(!isNegativeInf(f32(0.0)));
75 assert(!isNegativeInf(f32(-0.0)));75 assert(!isNegativeInf(f32(-0.0)));
76 assert(!isNegativeInf(f64(0.0)));76 assert(!isNegativeInf(f64(0.0)));
std/math/isnan.zig+1-1
...@@ -18,7 +18,7 @@ pub fn isNan(x: var) -> bool {...@@ -18,7 +18,7 @@ pub fn isNan(x: var) -> bool {
18 }18 }
19}19}
2020
21test "isNan" {21test "math.isNan" {
22 assert(isNan(math.nan(f32)));22 assert(isNan(math.nan(f32)));
23 assert(isNan(math.nan(f64)));23 assert(isNan(math.nan(f64)));
24 assert(!isNan(f32(1.0)));24 assert(!isNan(f32(1.0)));
std/math/isnormal.zig+1-1
...@@ -18,7 +18,7 @@ pub fn isNormal(x: var) -> bool {...@@ -18,7 +18,7 @@ pub fn isNormal(x: var) -> bool {
18 }18 }
19}19}
2020
21test "isNormal" {21test "math.isNormal" {
22 assert(!isNormal(math.nan(f32)));22 assert(!isNormal(math.nan(f32)));
23 assert(!isNormal(math.nan(f64)));23 assert(!isNormal(math.nan(f64)));
24 assert(isNormal(f32(1.0)));24 assert(isNormal(f32(1.0)));
std/math/ln.zig+3-1
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn ln(x: var) -> @typeOf(x) {4pub const ln = ln_workaround;
5
6pub fn ln_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);7 const T = @typeOf(x);
6 switch (T) {8 switch (T) {
7 f32 => @inlineCall(lnf, x),9 f32 => @inlineCall(lnf, x),
std/math/log.zig+17-25
...@@ -2,7 +2,10 @@ const math = @import("index.zig");...@@ -2,7 +2,10 @@ const math = @import("index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = @import("../debug.zig").assert;3const assert = @import("../debug.zig").assert;
44
5pub fn log(comptime base: usize, x: var) -> @typeOf(x) {5// TODO issue #393
6pub const log = log_workaround;
7
8pub fn log_workaround(comptime base: usize, x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (@typeId(T)) {10 switch (@typeId(T)) {
8 builtin.TypeId.Int => {11 builtin.TypeId.Int => {
...@@ -13,41 +16,30 @@ pub fn log(comptime base: usize, x: var) -> @typeOf(x) {...@@ -13,41 +16,30 @@ pub fn log(comptime base: usize, x: var) -> @typeOf(x) {
13 }16 }
14 },17 },
1518
16 builtin.TypeId.Float => {19 builtin.TypeId.Float => switch (T) {
17 return logf(base, x);20 f32 => switch (base) {
18 },
19
20 else => {
21 @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'");
22 },
23 }
24}
25
26fn logf(comptime base: usize, x: var) -> @typeOf(x) {
27 const T = @typeOf(x);
28 switch (T) {
29 f32 => {
30 switch (base) {
31 2 => return math.log2(x),21 2 => return math.log2(x),
32 10 => return math.log10(x),22 10 => return math.log10(x),
33 else => return f32(math.ln(f64(x)) / math.ln(f64(base))),23 else => return f32(math.ln(f64(x)) / math.ln(f64(base))),
34 }24 },
35 },
3625
37 f64 => {26 f64 => switch (base) {
38 switch (base) {
39 2 => return math.log2(x),27 2 => return math.log2(x),
40 10 => return math.log10(x),28 10 => return math.log10(x),
41 // NOTE: This likely is computed with reduced accuracy.29 // NOTE: This likely is computed with reduced accuracy.
42 else => return math.ln(x) / math.ln(f64(base)),30 else => return math.ln(x) / math.ln(f64(base)),
43 }31 },
32
33 else => @compileError("log not implemented for " ++ @typeName(T)),
44 },34 },
4535
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}
4941
50test "log_integer" {42test "math.log integer" {
51 assert(log(2, u8(0x1)) == 0);43 assert(log(2, u8(0x1)) == 0);
52 assert(log(2, u8(0x2)) == 1);44 assert(log(2, u8(0x2)) == 1);
53 assert(log(2, i16(0x72)) == 6);45 assert(log(2, i16(0x72)) == 6);
...@@ -55,7 +47,7 @@ test "log_integer" {...@@ -55,7 +47,7 @@ test "log_integer" {
55 assert(log(2, u64(0x7FF0123456789ABC)) == 62);47 assert(log(2, u64(0x7FF0123456789ABC)) == 62);
56}48}
5749
58test "log_float" {50test "math.log float" {
59 const epsilon = 0.000001;51 const epsilon = 0.000001;
6052
61 assert(math.approxEq(f32, log(6, f32(0.23947)), -0.797723, epsilon));53 assert(math.approxEq(f32, log(6, f32(0.23947)), -0.797723, epsilon));
...@@ -63,7 +55,7 @@ test "log_float" {...@@ -63,7 +55,7 @@ test "log_float" {
63 assert(math.approxEq(f64, log(123897, f64(12389216414)), 1.981724596, epsilon));55 assert(math.approxEq(f64, log(123897, f64(12389216414)), 1.981724596, epsilon));
64}56}
6557
66test "log_float_special" {58test "math.log float_special" {
67 assert(log(2, f32(0.2301974)) == math.log2(f32(0.2301974)));59 assert(log(2, f32(0.2301974)) == math.log2(f32(0.2301974)));
68 assert(log(10, f32(0.2301974)) == math.log10(f32(0.2301974)));60 assert(log(10, f32(0.2301974)) == math.log10(f32(0.2301974)));
6961
std/math/log10.zig+25-22
...@@ -1,16 +1,19 @@...@@ -1,16 +1,19 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn log10(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const log10 = log10_workaround;
6
7pub fn log10_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(log10f, x),10 f32 => @inlineCall(log10_32, x),
8 f64 => @inlineCall(log10d, x),11 f64 => @inlineCall(log10_64, x),
9 else => @compileError("log10 not implemented for " ++ @typeName(T)),12 else => @compileError("log10 not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13fn log10f(x_: f32) -> f32 {16fn log10_32(x_: f32) -> f32 {
14 const ivln10hi: f32 = 4.3432617188e-01;17 const ivln10hi: f32 = 4.3432617188e-01;
15 const ivln10lo: f32 = -3.1689971365e-05;18 const ivln10lo: f32 = -3.1689971365e-05;
16 const log10_2hi: f32 = 3.0102920532e-01;19 const log10_2hi: f32 = 3.0102920532e-01;
...@@ -70,7 +73,7 @@ fn log10f(x_: f32) -> f32 {...@@ -70,7 +73,7 @@ fn log10f(x_: f32) -> f32 {
70 dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi73 dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi
71}74}
7275
73fn log10d(x_: f64) -> f64 {76fn log10_64(x_: f64) -> f64 {
74 const ivln10hi: f64 = 4.34294481878168880939e-01;77 const ivln10hi: f64 = 4.34294481878168880939e-01;
75 const ivln10lo: f64 = 2.50829467116452752298e-11;78 const ivln10lo: f64 = 2.50829467116452752298e-11;
76 const log10_2hi: f64 = 3.01029995663611771306e-01;79 const log10_2hi: f64 = 3.01029995663611771306e-01;
...@@ -147,29 +150,29 @@ fn log10d(x_: f64) -> f64 {...@@ -147,29 +150,29 @@ fn log10d(x_: f64) -> f64 {
147 val_lo + val_hi150 val_lo + val_hi
148}151}
149152
150test "log10" {153test "math.log10" {
151 assert(log10(f32(0.2)) == log10f(0.2));154 assert(log10(f32(0.2)) == log10_32(0.2));
152 assert(log10(f64(0.2)) == log10d(0.2));155 assert(log10(f64(0.2)) == log10_64(0.2));
153}156}
154157
155test "log10f" {158test "math.log10_32" {
156 const epsilon = 0.000001;159 const epsilon = 0.000001;
157160
158 assert(math.approxEq(f32, log10f(0.2), -0.698970, epsilon));161 assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
159 assert(math.approxEq(f32, log10f(0.8923), -0.049489, epsilon));162 assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
160 assert(math.approxEq(f32, log10f(1.5), 0.176091, epsilon));163 assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
161 assert(math.approxEq(f32, log10f(37.45), 1.573452, epsilon));164 assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
162 assert(math.approxEq(f32, log10f(89.123), 1.94999, epsilon));165 assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
163 assert(math.approxEq(f32, log10f(123123.234375), 5.09034, epsilon));166 assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
164}167}
165168
166test "log10d" {169test "math.log10_64" {
167 const epsilon = 0.000001;170 const epsilon = 0.000001;
168171
169 assert(math.approxEq(f64, log10d(0.2), -0.698970, epsilon));172 assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
170 assert(math.approxEq(f64, log10d(0.8923), -0.049489, epsilon));173 assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
171 assert(math.approxEq(f64, log10d(1.5), 0.176091, epsilon));174 assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
172 assert(math.approxEq(f64, log10d(37.45), 1.573452, epsilon));175 assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
173 assert(math.approxEq(f64, log10d(89.123), 1.94999, epsilon));176 assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
174 assert(math.approxEq(f64, log10d(123123.234375), 5.09034, 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,16 +1,19 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn log1p(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const log1p = log1p_workaround;
6
7pub fn log1p_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(log1pf, x),10 f32 => @inlineCall(log1p_32, x),
8 f64 => @inlineCall(log1pd, x),11 f64 => @inlineCall(log1p_64, x),
9 else => @compileError("log1p not implemented for " ++ @typeName(T)),12 else => @compileError("log1p not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13fn log1pf(x: f32) -> f32 {16fn log1p_32(x: f32) -> f32 {
14 const ln2_hi = 6.9313812256e-01;17 const ln2_hi = 6.9313812256e-01;
15 const ln2_lo = 9.0580006145e-06;18 const ln2_lo = 9.0580006145e-06;
16 const Lg1: f32 = 0xaaaaaa.0p-24;19 const Lg1: f32 = 0xaaaaaa.0p-24;
...@@ -86,7 +89,7 @@ fn log1pf(x: f32) -> f32 {...@@ -86,7 +89,7 @@ fn log1pf(x: f32) -> f32 {
86 s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi89 s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi
87}90}
8891
89fn log1pd(x: f64) -> f64 {92fn log1p_64(x: f64) -> f64 {
90 const ln2_hi: f64 = 6.93147180369123816490e-01;93 const ln2_hi: f64 = 6.93147180369123816490e-01;
91 const ln2_lo: f64 = 1.90821492927058770002e-10;94 const ln2_lo: f64 = 1.90821492927058770002e-10;
92 const Lg1: f64 = 6.666666666666735130e-01;95 const Lg1: f64 = 6.666666666666735130e-01;
...@@ -167,31 +170,31 @@ fn log1pd(x: f64) -> f64 {...@@ -167,31 +170,31 @@ fn log1pd(x: f64) -> f64 {
167 s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi170 s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi
168}171}
169172
170test "log1p" {173test "math.log1p" {
171 assert(log1p(f32(0.0)) == log1pf(0.0));174 assert(log1p(f32(0.0)) == log1p_32(0.0));
172 assert(log1p(f64(0.0)) == log1pd(0.0));175 assert(log1p(f64(0.0)) == log1p_64(0.0));
173}176}
174177
175test "log1pf" {178test "math.log1p_32" {
176 const epsilon = 0.000001;179 const epsilon = 0.000001;
177180
178 assert(math.approxEq(f32, log1pf(0.0), 0.0, epsilon));181 assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
179 assert(math.approxEq(f32, log1pf(0.2), 0.182322, epsilon));182 assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
180 assert(math.approxEq(f32, log1pf(0.8923), 0.637793, epsilon));183 assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
181 assert(math.approxEq(f32, log1pf(1.5), 0.916291, epsilon));184 assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
182 assert(math.approxEq(f32, log1pf(37.45), 3.649359, epsilon));185 assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
183 assert(math.approxEq(f32, log1pf(89.123), 4.501175, epsilon));186 assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
184 assert(math.approxEq(f32, log1pf(123123.234375), 11.720949, epsilon));187 assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
185}188}
186189
187test "log1pd" {190test "math.log1p_64" {
188 const epsilon = 0.000001;191 const epsilon = 0.000001;
189192
190 assert(math.approxEq(f64, log1pd(0.0), 0.0, epsilon));193 assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
191 assert(math.approxEq(f64, log1pd(0.2), 0.182322, epsilon));194 assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
192 assert(math.approxEq(f64, log1pd(0.8923), 0.637793, epsilon));195 assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
193 assert(math.approxEq(f64, log1pd(1.5), 0.916291, epsilon));196 assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
194 assert(math.approxEq(f64, log1pd(37.45), 3.649359, epsilon));197 assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
195 assert(math.approxEq(f64, log1pd(89.123), 4.501175, epsilon));198 assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
196 assert(math.approxEq(f64, log1pd(123123.234375), 11.720949, 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,16 +1,19 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn log2(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const log2 = log2_workaround;
6
7pub fn log2_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(log2f, x),10 f32 => @inlineCall(log2_32, x),
8 f64 => @inlineCall(log2d, x),11 f64 => @inlineCall(log2_64, x),
9 else => @compileError("log2 not implemented for " ++ @typeName(T)),12 else => @compileError("log2 not implemented for " ++ @typeName(T)),
10 }13 }
11}14}
1215
13fn log2f(x_: f32) -> f32 {16fn log2_32(x_: f32) -> f32 {
14 const ivln2hi: f32 = 1.4428710938e+00;17 const ivln2hi: f32 = 1.4428710938e+00;
15 const ivln2lo: f32 = -1.7605285393e-04;18 const ivln2lo: f32 = -1.7605285393e-04;
16 const Lg1: f32 = 0xaaaaaa.0p-24;19 const Lg1: f32 = 0xaaaaaa.0p-24;
...@@ -66,7 +69,7 @@ fn log2f(x_: f32) -> f32 {...@@ -66,7 +69,7 @@ fn log2f(x_: f32) -> f32 {
66 (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k)69 (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k)
67}70}
6871
69fn log2d(x_: f64) -> f64 {72fn log2_64(x_: f64) -> f64 {
70 const ivln2hi: f64 = 1.44269504072144627571e+00;73 const ivln2hi: f64 = 1.44269504072144627571e+00;
71 const ivln2lo: f64 = 1.67517131648865118353e-10;74 const ivln2lo: f64 = 1.67517131648865118353e-10;
72 const Lg1: f64 = 6.666666666666735130e-01;75 const Lg1: f64 = 6.666666666666735130e-01;
...@@ -139,27 +142,27 @@ fn log2d(x_: f64) -> f64 {...@@ -139,27 +142,27 @@ fn log2d(x_: f64) -> f64 {
139 val_lo + val_hi142 val_lo + val_hi
140}143}
141144
142test "log2" {145test "math.log2" {
143 assert(log2(f32(0.2)) == log2f(0.2));146 assert(log2(f32(0.2)) == log2_32(0.2));
144 assert(log2(f64(0.2)) == log2d(0.2));147 assert(log2(f64(0.2)) == log2_64(0.2));
145}148}
146149
147test "log2f" {150test "math.log2_32" {
148 const epsilon = 0.000001;151 const epsilon = 0.000001;
149152
150 assert(math.approxEq(f32, log2f(0.2), -2.321928, epsilon));153 assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
151 assert(math.approxEq(f32, log2f(0.8923), -0.164399, epsilon));154 assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
152 assert(math.approxEq(f32, log2f(1.5), 0.584962, epsilon));155 assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
153 assert(math.approxEq(f32, log2f(37.45), 5.226894, epsilon));156 assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
154 assert(math.approxEq(f32, log2f(123123.234375), 16.909744, epsilon));157 assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
155}158}
156159
157test "log2d" {160test "math.log2_64" {
158 const epsilon = 0.000001;161 const epsilon = 0.000001;
159162
160 assert(math.approxEq(f64, log2d(0.2), -2.321928, epsilon));163 assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
161 assert(math.approxEq(f64, log2d(0.8923), -0.164399, epsilon));164 assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
162 assert(math.approxEq(f64, log2d(1.5), 0.584962, epsilon));165 assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
163 assert(math.approxEq(f64, log2d(37.45), 5.226894, epsilon));166 assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
164 assert(math.approxEq(f64, log2d(123123.234375), 16.909744, 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,6 +1,9 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4// TODO issue #393
5pub const modf = modf_workaround;
6
4fn modf_result(comptime T: type) -> type {7fn modf_result(comptime T: type) -> type {
5 struct {8 struct {
6 fpart: T,9 fpart: T,
...@@ -10,7 +13,7 @@ fn modf_result(comptime T: type) -> type {...@@ -10,7 +13,7 @@ fn modf_result(comptime T: type) -> type {
10pub const modf32_result = modf_result(f32);13pub const modf32_result = modf_result(f32);
11pub const modf64_result = modf_result(f64);14pub const modf64_result = modf_result(f64);
1215
13pub fn modf(x: var) -> modf_result(@typeOf(x)) {16pub fn modf_workaround(x: var) -> modf_result(@typeOf(x)) {
14 const T = @typeOf(x);17 const T = @typeOf(x);
15 switch (T) {18 switch (T) {
16 f32 => @inlineCall(modf32, x),19 f32 => @inlineCall(modf32, x),
...@@ -95,7 +98,7 @@ fn modf64(x: f64) -> modf64_result {...@@ -95,7 +98,7 @@ fn modf64(x: f64) -> modf64_result {
95 result98 result
96}99}
97100
98test "modf" {101test "math.modf" {
99 const a = modf(f32(1.0));102 const a = modf(f32(1.0));
100 const b = modf32(1.0);103 const b = modf32(1.0);
101 // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still.104 // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still.
...@@ -106,7 +109,7 @@ test "modf" {...@@ -106,7 +109,7 @@ test "modf" {
106 assert(a.ipart == b.ipart and a.fpart == b.fpart);109 assert(a.ipart == b.ipart and a.fpart == b.fpart);
107}110}
108111
109test "modf32" {112test "math.modf32" {
110 const epsilon = 0.000001;113 const epsilon = 0.000001;
111 var r: modf32_result = undefined;114 var r: modf32_result = undefined;
112115
...@@ -131,7 +134,7 @@ test "modf32" {...@@ -131,7 +134,7 @@ test "modf32" {
131 assert(math.approxEq(f32, r.fpart, 0.340820, epsilon));134 assert(math.approxEq(f32, r.fpart, 0.340820, epsilon));
132}135}
133136
134test "modf64" {137test "math.modf64" {
135 const epsilon = 0.000001;138 const epsilon = 0.000001;
136 var r: modf64_result = undefined;139 var r: modf64_result = undefined;
137140
std/math/nan.zig+3-1
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1const math = @import("index.zig");1const math = @import("index.zig");
22
3pub fn nan(comptime T: type) -> T {3pub const nan = nan_workaround;
4
5pub fn nan_workaround(comptime T: type) -> T {
4 switch (T) {6 switch (T) {
5 f32 => @bitCast(f32, math.nan_u32),7 f32 => @bitCast(f32, math.nan_u32),
6 f64 => @bitCast(f64, math.nan_u64),8 f64 => @bitCast(f64, math.nan_u64),
std/math/oindex.zig deleted-274
...@@ -1,274 +0,0 @@
1const assert = @import("../debug.zig").assert;
2const builtin = @import("builtin");
3
4pub const frexp = @import("frexp.zig").frexp;
5
6pub const Cmp = enum {
7 Less,
8 Equal,
9 Greater,
10};
11
12pub fn min(x: var, y: var) -> @typeOf(x + y) {
13 if (x < y) x else y
14}
15
16test "math.min" {
17 assert(min(i32(-1), i32(2)) == -1);
18}
19
20pub fn max(x: var, y: var) -> @typeOf(x + y) {
21 if (x > y) x else y
22}
23
24test "math.max" {
25 assert(max(i32(-1), i32(2)) == 2);
26}
27
28error Overflow;
29pub 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
34error Overflow;
35pub 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
40error Overflow;
41pub 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
46pub fn negate(x: var) -> %@typeOf(x) {
47 return sub(@typeOf(x), 0, x);
48}
49
50error Overflow;
51pub 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
56test "math overflow functions" {
57 testOverflow();
58 comptime testOverflow();
59}
60
61fn 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
69error Overflow;
70pub 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
82test "math.absInt" {
83 testAbsInt();
84 comptime testAbsInt();
85}
86fn testAbsInt() {
87 assert(%%absInt(i32(-10)) == 10);
88 assert(%%absInt(i32(10)) == 10);
89}
90
91pub const absFloat = @import("fabs.zig").fabs;
92
93error DivisionByZero;
94error Overflow;
95pub 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
104test "math.divTrunc" {
105 testDivTrunc();
106 comptime testDivTrunc();
107}
108fn 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
118error DivisionByZero;
119error Overflow;
120pub 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
129test "math.divFloor" {
130 testDivFloor();
131 comptime testDivFloor();
132}
133fn 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
143error DivisionByZero;
144error Overflow;
145error UnexpectedRemainder;
146pub 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
158test "math.divExact" {
159 testDivExact();
160 comptime testDivExact();
161}
162fn 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
174error DivisionByZero;
175error NegativeDenominator;
176pub 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
185test "math.mod" {
186 testMod();
187 comptime testMod();
188}
189fn 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
201error DivisionByZero;
202error NegativeDenominator;
203pub 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
212test "math.rem" {
213 testRem();
214 comptime testRem();
215}
216fn 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.
230pub 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
238test "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.
251error Overflow;
252pub 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
266test "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,8 +1,11 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4// TODO issue #393
5pub const pow = pow_workaround;
6
4// This implementation is taken from the go stlib, musl is a bit more complex.7// This implementation is taken from the go stlib, musl is a bit more complex.
5pub fn pow(comptime T: type, x: T, y: T) -> T {8pub fn pow_workaround(comptime T: type, x: T, y: T) -> T {
69
7 @setFloatMode(this, @import("builtin").FloatMode.Strict);10 @setFloatMode(this, @import("builtin").FloatMode.Strict);
811
...@@ -158,9 +161,7 @@ test "math.pow" {...@@ -158,9 +161,7 @@ test "math.pow" {
158 assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));161 assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));
159 assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));162 assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
160 assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));163 assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
161164 assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
162 // TODO: Determine why aborting on release mode.
163 // assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
164165
165 // assert(math.approxEq(f32, pow(f64, 0.0, 3.3), 0.0, epsilon)); // TODO: Handle div zero166 // assert(math.approxEq(f32, pow(f64, 0.0, 3.3), 0.0, epsilon)); // TODO: Handle div zero
166 assert(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));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,7 +2,10 @@ const builtin = @import("builtin");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
3const math = @import("index.zig");3const math = @import("index.zig");
44
5pub fn round(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const round = round_workaround;
7
8pub fn round_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(round32, x),11 f32 => @inlineCall(round32, x),
...@@ -85,19 +88,19 @@ fn round64(x_: f64) -> f64 {...@@ -85,19 +88,19 @@ fn round64(x_: f64) -> f64 {
85 }88 }
86}89}
8790
88test "round" {91test "math.round" {
89 assert(round(f32(1.3)) == round32(1.3));92 assert(round(f32(1.3)) == round32(1.3));
90 assert(round(f64(1.3)) == round64(1.3));93 assert(round(f64(1.3)) == round64(1.3));
91}94}
9295
93test "round32" {96test "math.round32" {
94 assert(round32(1.3) == 1.0);97 assert(round32(1.3) == 1.0);
95 assert(round32(-1.3) == -1.0);98 assert(round32(-1.3) == -1.0);
96 assert(round32(0.2) == 0.0);99 assert(round32(0.2) == 0.0);
97 assert(round32(1.8) == 2.0);100 assert(round32(1.8) == 2.0);
98}101}
99102
100test "round64" {103test "math.round64" {
101 assert(round64(1.3) == 1.0);104 assert(round64(1.3) == 1.0);
102 assert(round64(-1.3) == -1.0);105 assert(round64(-1.3) == -1.0);
103 assert(round64(0.2) == 0.0);106 assert(round64(0.2) == 0.0);
std/math/scalbn.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn scalbn(x: var, n: i32) -> @typeOf(x) {4// TODO issue #393
5pub const scalbn = scalbn_workaround;
6
7pub fn scalbn_workaround(x: var, n: i32) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(scalbn32, x, n),10 f32 => @inlineCall(scalbn32, x, n),
...@@ -71,15 +74,15 @@ fn scalbn64(x: f64, n_: i32) -> f64 {...@@ -71,15 +74,15 @@ fn scalbn64(x: f64, n_: i32) -> f64 {
71 y * @bitCast(f64, u)74 y * @bitCast(f64, u)
72}75}
7376
74test "scalbn" {77test "math.scalbn" {
75 assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));78 assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
76 assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));79 assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
77}80}
7881
79test "scalbn32" {82test "math.scalbn32" {
80 assert(scalbn32(1.5, 4) == 24.0);83 assert(scalbn32(1.5, 4) == 24.0);
81}84}
8285
83test "scalbn64" {86test "math.scalbn64" {
84 assert(scalbn64(1.5, 4) == 24.0);87 assert(scalbn64(1.5, 4) == 24.0);
85}88}
std/math/signbit.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn signbit(x: var) -> bool {4// TODO issue #393
5pub const signbit = signbit_workaround;
6
7pub fn signbit_workaround(x: var) -> bool {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(signbit32, x),10 f32 => @inlineCall(signbit32, x),
...@@ -20,17 +23,17 @@ fn signbit64(x: f64) -> bool {...@@ -20,17 +23,17 @@ fn signbit64(x: f64) -> bool {
20 bits >> 63 != 023 bits >> 63 != 0
21}24}
2225
23test "signbit" {26test "math.signbit" {
24 assert(signbit(f32(4.0)) == signbit32(4.0));27 assert(signbit(f32(4.0)) == signbit32(4.0));
25 assert(signbit(f64(4.0)) == signbit64(4.0));28 assert(signbit(f64(4.0)) == signbit64(4.0));
26}29}
2730
28test "signbit32" {31test "math.signbit32" {
29 assert(!signbit32(4.0));32 assert(!signbit32(4.0));
30 assert(signbit32(-3.0));33 assert(signbit32(-3.0));
31}34}
3235
33test "signbit64" {36test "math.signbit64" {
34 assert(!signbit64(4.0));37 assert(!signbit64(4.0));
35 assert(signbit64(-3.0));38 assert(signbit64(-3.0));
36}39}
std/math/sin.zig+7-4
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn sin(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const sin = sin_workaround;
6
7pub fn sin_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(sin32, x),10 f32 => @inlineCall(sin32, x),
...@@ -135,12 +138,12 @@ fn sin64(x_: f64) -> f64 {...@@ -135,12 +138,12 @@ fn sin64(x_: f64) -> f64 {
135 }138 }
136}139}
137140
138test "sin" {141test "math.sin" {
139 assert(sin(f32(0.0)) == sin32(0.0));142 assert(sin(f32(0.0)) == sin32(0.0));
140 assert(sin(f64(0.0)) == sin64(0.0));143 assert(sin(f64(0.0)) == sin64(0.0));
141}144}
142145
143test "sin32" {146test "math.sin32" {
144 const epsilon = 0.000001;147 const epsilon = 0.000001;
145148
146 assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon));149 assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
...@@ -151,7 +154,7 @@ test "sin32" {...@@ -151,7 +154,7 @@ test "sin32" {
151 assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));154 assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
152}155}
153156
154test "sin64" {157test "math.sin64" {
155 const epsilon = 0.000001;158 const epsilon = 0.000001;
156159
157 assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon));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,11 +2,14 @@ const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
3const expo2 = @import("_expo2.zig").expo2;3const expo2 = @import("_expo2.zig").expo2;
44
5pub fn sinh(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const sinh = sinh_workaround;
7
8pub fn sinh_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(sinhf, x),11 f32 => @inlineCall(sinh32, x),
9 f64 => @inlineCall(sinhd, x),12 f64 => @inlineCall(sinh64, x),
10 else => @compileError("sinh not implemented for " ++ @typeName(T)),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,7 +17,7 @@ pub fn sinh(x: var) -> @typeOf(x) {
14// sinh(x) = (exp(x) - 1 / exp(x)) / 217// sinh(x) = (exp(x) - 1 / exp(x)) / 2
15// = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 218// = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 2
16// = x + x^3 / 6 + o(x^5)19// = x + x^3 / 6 + o(x^5)
17fn sinhf(x: f32) -> f32 {20fn sinh32(x: f32) -> f32 {
18 const u = @bitCast(u32, x);21 const u = @bitCast(u32, x);
19 const ux = u & 0x7FFFFFFF;22 const ux = u & 0x7FFFFFFF;
20 const ax = @bitCast(f32, ux);23 const ax = @bitCast(f32, ux);
...@@ -41,7 +44,7 @@ fn sinhf(x: f32) -> f32 {...@@ -41,7 +44,7 @@ fn sinhf(x: f32) -> f32 {
41 2 * h * expo2(ax)44 2 * h * expo2(ax)
42}45}
4346
44fn sinhd(x: f64) -> f64 {47fn sinh64(x: f64) -> f64 {
45 const u = @bitCast(u64, x);48 const u = @bitCast(u64, x);
46 const w = u32(u >> 32);49 const w = u32(u >> 32);
47 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));50 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
...@@ -69,25 +72,25 @@ fn sinhd(x: f64) -> f64 {...@@ -69,25 +72,25 @@ fn sinhd(x: f64) -> f64 {
69 2 * h * expo2(ax)72 2 * h * expo2(ax)
70}73}
7174
72test "sinh" {75test "math.sinh" {
73 assert(sinh(f32(1.5)) == sinhf(1.5));76 assert(sinh(f32(1.5)) == sinh32(1.5));
74 assert(sinh(f64(1.5)) == sinhd(1.5));77 assert(sinh(f64(1.5)) == sinh64(1.5));
75}78}
7679
77test "sinhf" {80test "math.sinh32" {
78 const epsilon = 0.000001;81 const epsilon = 0.000001;
7982
80 assert(math.approxEq(f32, sinhf(0.0), 0.0, epsilon));83 assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
81 assert(math.approxEq(f32, sinhf(0.2), 0.201336, epsilon));84 assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
82 assert(math.approxEq(f32, sinhf(0.8923), 1.015512, epsilon));85 assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
83 assert(math.approxEq(f32, sinhf(1.5), 2.129279, epsilon));86 assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
84}87}
8588
86test "sinhd" {89test "math.sinh64" {
87 const epsilon = 0.000001;90 const epsilon = 0.000001;
8891
89 assert(math.approxEq(f64, sinhd(0.0), 0.0, epsilon));92 assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
90 assert(math.approxEq(f64, sinhd(0.2), 0.201336, epsilon));93 assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
91 assert(math.approxEq(f64, sinhd(0.8923), 1.015512, epsilon));94 assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
92 assert(math.approxEq(f64, sinhd(1.5), 2.129279, 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,7 +1,10 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn sqrt(x: var) -> @typeOf(x) {4// TODO issue #393
5pub const sqrt = sqrt_workaround;
6
7pub fn sqrt_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);8 const T = @typeOf(x);
6 switch (T) {9 switch (T) {
7 f32 => @inlineCall(sqrt32, x),10 f32 => @inlineCall(sqrt32, x),
...@@ -219,12 +222,12 @@ fn sqrt64(x: f64) -> f64 {...@@ -219,12 +222,12 @@ fn sqrt64(x: f64) -> f64 {
219 @bitCast(f64, uz)222 @bitCast(f64, uz)
220}223}
221224
222test "sqrt" {225test "math.sqrt" {
223 assert(sqrt(f32(0.0)) == sqrt32(0.0));226 assert(sqrt(f32(0.0)) == sqrt32(0.0));
224 assert(sqrt(f64(0.0)) == sqrt64(0.0));227 assert(sqrt(f64(0.0)) == sqrt64(0.0));
225}228}
226229
227test "sqrt32" {230test "math.sqrt32" {
228 const epsilon = 0.000001;231 const epsilon = 0.000001;
229232
230 assert(sqrt32(0.0) == 0.0);233 assert(sqrt32(0.0) == 0.0);
...@@ -238,7 +241,7 @@ test "sqrt32" {...@@ -238,7 +241,7 @@ test "sqrt32" {
238 assert(math.approxEq(f32, sqrt32(8942.230469), 94.563370, epsilon));241 assert(math.approxEq(f32, sqrt32(8942.230469), 94.563370, epsilon));
239}242}
240243
241test "sqrt64" {244test "math.sqrt64" {
242 const epsilon = 0.000001;245 const epsilon = 0.000001;
243246
244 assert(sqrt64(0.0) == 0.0);247 assert(sqrt64(0.0) == 0.0);
std/math/tan.zig+6-4
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn tan(x: var) -> @typeOf(x) {4pub const tan = tan_workaround;
5
6pub fn tan_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);7 const T = @typeOf(x);
6 switch (T) {8 switch (T) {
7 f32 => @inlineCall(tan32, x),9 f32 => @inlineCall(tan32, x),
...@@ -122,12 +124,12 @@ fn tan64(x_: f64) -> f64 {...@@ -122,12 +124,12 @@ fn tan64(x_: f64) -> f64 {
122 r124 r
123}125}
124126
125test "tan" {127test "math.tan" {
126 assert(tan(f32(0.0)) == tan32(0.0));128 assert(tan(f32(0.0)) == tan32(0.0));
127 assert(tan(f64(0.0)) == tan64(0.0));129 assert(tan(f64(0.0)) == tan64(0.0));
128}130}
129131
130test "tan32" {132test "math.tan32" {
131 const epsilon = 0.000001;133 const epsilon = 0.000001;
132134
133 assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon));135 assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
...@@ -138,7 +140,7 @@ test "tan32" {...@@ -138,7 +140,7 @@ test "tan32" {
138 assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));140 assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
139}141}
140142
141test "tan64" {143test "math.tan64" {
142 const epsilon = 0.000001;144 const epsilon = 0.000001;
143145
144 assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon));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,11 +2,14 @@ const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
3const expo2 = @import("_expo2.zig").expo2;3const expo2 = @import("_expo2.zig").expo2;
44
5pub fn tanh(x: var) -> @typeOf(x) {5// TODO issue #393
6pub const tanh = tanh_workaround;
7
8pub fn tanh_workaround(x: var) -> @typeOf(x) {
6 const T = @typeOf(x);9 const T = @typeOf(x);
7 switch (T) {10 switch (T) {
8 f32 => @inlineCall(tanhf, x),11 f32 => @inlineCall(tanh32, x),
9 f64 => @inlineCall(tanhd, x),12 f64 => @inlineCall(tanh64, x),
10 else => @compileError("tanh not implemented for " ++ @typeName(T)),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,7 +17,7 @@ pub fn tanh(x: var) -> @typeOf(x) {
14// tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))17// tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
15// = (exp(2x) - 1) / (exp(2x) - 1 + 2)18// = (exp(2x) - 1) / (exp(2x) - 1 + 2)
16// = (1 - exp(-2x)) / (exp(-2x) - 1 + 2)19// = (1 - exp(-2x)) / (exp(-2x) - 1 + 2)
17fn tanhf(x: f32) -> f32 {20fn tanh32(x: f32) -> f32 {
18 const u = @bitCast(u32, x);21 const u = @bitCast(u32, x);
19 const ux = u & 0x7FFFFFFF;22 const ux = u & 0x7FFFFFFF;
20 const ax = @bitCast(f32, ux);23 const ax = @bitCast(f32, ux);
...@@ -54,7 +57,7 @@ fn tanhf(x: f32) -> f32 {...@@ -54,7 +57,7 @@ fn tanhf(x: f32) -> f32 {
54 }57 }
55}58}
5659
57fn tanhd(x: f64) -> f64 {60fn tanh64(x: f64) -> f64 {
58 const u = @bitCast(u64, x);61 const u = @bitCast(u64, x);
59 const w = u32(u >> 32);62 const w = u32(u >> 32);
60 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));63 const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
...@@ -94,27 +97,27 @@ fn tanhd(x: f64) -> f64 {...@@ -94,27 +97,27 @@ fn tanhd(x: f64) -> f64 {
94 }97 }
95}98}
9699
97test "tanh" {100test "math.tanh" {
98 assert(tanh(f32(1.5)) == tanhf(1.5));101 assert(tanh(f32(1.5)) == tanh32(1.5));
99 assert(tanh(f64(1.5)) == tanhd(1.5));102 assert(tanh(f64(1.5)) == tanh64(1.5));
100}103}
101104
102test "tanhf" {105test "math.tanh32" {
103 const epsilon = 0.000001;106 const epsilon = 0.000001;
104107
105 assert(math.approxEq(f32, tanhf(0.0), 0.0, epsilon));108 assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
106 assert(math.approxEq(f32, tanhf(0.2), 0.197375, epsilon));109 assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
107 assert(math.approxEq(f32, tanhf(0.8923), 0.712528, epsilon));110 assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
108 assert(math.approxEq(f32, tanhf(1.5), 0.905148, epsilon));111 assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
109 assert(math.approxEq(f32, tanhf(37.45), 1.0, epsilon));112 assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
110}113}
111114
112test "tanhd" {115test "math.tanh64" {
113 const epsilon = 0.000001;116 const epsilon = 0.000001;
114117
115 assert(math.approxEq(f64, tanhd(0.0), 0.0, epsilon));118 assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
116 assert(math.approxEq(f64, tanhd(0.2), 0.197375, epsilon));119 assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
117 assert(math.approxEq(f64, tanhd(0.8923), 0.712528, epsilon));120 assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
118 assert(math.approxEq(f64, tanhd(1.5), 0.905148, epsilon));121 assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
119 assert(math.approxEq(f64, tanhd(37.45), 1.0, 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,7 +1,9 @@
1const math = @import("index.zig");1const math = @import("index.zig");
2const assert = @import("../debug.zig").assert;2const assert = @import("../debug.zig").assert;
33
4pub fn trunc(x: var) -> @typeOf(x) {4pub const trunc = trunc_workaround;
5
6pub fn trunc_workaround(x: var) -> @typeOf(x) {
5 const T = @typeOf(x);7 const T = @typeOf(x);
6 switch (T) {8 switch (T) {
7 f32 => @inlineCall(trunc32, x),9 f32 => @inlineCall(trunc32, x),
...@@ -52,18 +54,18 @@ fn trunc64(x: f64) -> f64 {...@@ -52,18 +54,18 @@ fn trunc64(x: f64) -> f64 {
52 }54 }
53}55}
5456
55test "trunc" {57test "math.trunc" {
56 assert(trunc(f32(1.3)) == trunc32(1.3));58 assert(trunc(f32(1.3)) == trunc32(1.3));
57 assert(trunc(f64(1.3)) == trunc64(1.3));59 assert(trunc(f64(1.3)) == trunc64(1.3));
58}60}
5961
60test "trunc32" {62test "math.trunc32" {
61 assert(trunc32(1.3) == 1.0);63 assert(trunc32(1.3) == 1.0);
62 assert(trunc32(-1.3) == -1.0);64 assert(trunc32(-1.3) == -1.0);
63 assert(trunc32(0.2) == 0.0);65 assert(trunc32(0.2) == 0.0);
64}66}
6567
66test "trunc64" {68test "math.trunc64" {
67 assert(trunc64(1.3) == 1.0);69 assert(trunc64(1.3) == 1.0);
68 assert(trunc64(-1.3) == -1.0);70 assert(trunc64(-1.3) == -1.0);
69 assert(trunc64(0.2) == 0.0);71 assert(trunc64(0.2) == 0.0);