aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/floatop.zig
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2022-02-04 20:21:15 +0100
committerAndrew Kelley <andrew@ziglang.org>2022-02-09 20:29:41 -0500
commit7f0cf395aa74eb5ea250bd28f7525b3036790a6a (patch)
treee2faf4e4a19836331d3e47180438fab4db4fb178 /test/behavior/floatop.zig
parent44b5fdf3266f11607313bc9990a876b5a7f9e174 (diff)
downloadzig-7f0cf395aa74eb5ea250bd28f7525b3036790a6a.tar.gz
zig-7f0cf395aa74eb5ea250bd28f7525b3036790a6a.zip
stage2: implement all builtin floatops for f{16,32,64}
- Merge `floatop.zig` and `floatop_stage1.zig` since most tests now pass on stage2. - Add more behavior tests for a bunch of functions.
Diffstat (limited to 'test/behavior/floatop.zig')
-rw-r--r--test/behavior/floatop.zig362
1 files changed, 349 insertions, 13 deletions
diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig
index 7807c690f6..ed632c26c5 100644
--- a/test/behavior/floatop.zig
+++ b/test/behavior/floatop.zig
@@ -1,12 +1,22 @@
const std = @import("std");
+const builtin = @import("builtin");
const expect = std.testing.expect;
const math = std.math;
const pi = std.math.pi;
const e = std.math.e;
const Vector = std.meta.Vector;
+const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
+const epsilon_16 = 0.001;
const epsilon = 0.000001;
+fn epsForType(comptime T: type) T {
+ return switch (T) {
+ f16 => @as(f16, epsilon_16),
+ else => @as(T, epsilon),
+ };
+}
+
test "floating point comparisons" {
try testFloatComparisons();
comptime try testFloatComparisons();
@@ -79,19 +89,37 @@ test "@sqrt" {
}
fn testSqrt() !void {
- {
- var a: f16 = 4;
- try expect(@sqrt(a) == 2);
- }
- {
- var a: f32 = 9;
- try expect(@sqrt(a) == 3);
- var b: f32 = 1.1;
- try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
- }
- {
- var a: f64 = 25;
- try expect(@sqrt(a) == 5);
+ try expect(@sqrt(@as(f16, 4)) == 2);
+ try expect(@sqrt(@as(f32, 9)) == 3);
+ try expect(@sqrt(@as(f64, 25)) == 5);
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon));
+
+ if (builtin.zig_backend == .stage1) {
+ if (has_f80_rt) {
+ var a: f80 = 25;
+ try expect(@sqrt(a) == 5);
+ }
+ {
+ const a: comptime_float = 25.0;
+ try expect(@sqrt(a) == 5.0);
+ }
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ //{
+ // var a: f128 = 49;
+ //try expect(@sqrt(a) == 7);
+ //}
+
+ // TODO Implement Vector support for stage2
+ {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @sqrt(v);
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
+ }
}
}
@@ -114,3 +142,311 @@ test "more @sqrt f16 tests" {
try expect(math.isNan(@sqrt(@as(f16, -1.0))));
try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
}
+
+test "@sin" {
+ comptime try testSin();
+ try testSin();
+}
+
+fn testSin() !void {
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @sin(v);
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
+
+ // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)`
+ // so skip the rest of the tests.
+ return;
+ }
+
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@sin(@as(ty, 0)) == 0);
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps));
+ try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
+ }
+}
+
+test "@cos" {
+ comptime try testCos();
+ try testCos();
+}
+
+fn testCos() !void {
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
+ var result = @cos(v);
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
+
+ // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)`
+ // so skip the rest of the tests.
+ return;
+ }
+
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@cos(@as(ty, 0)) == 1);
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps));
+ try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));
+ }
+}
+
+test "@exp" {
+ comptime try testExp();
+ try testExp();
+}
+
+fn testExp() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@exp(@as(ty, 0)) == 1);
+ try expect(math.approxEqAbs(ty, @exp(@as(ty, 2)), 7.389056098930650, eps));
+ try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @exp(v);
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@exp2" {
+ comptime try testExp2();
+ try testExp2();
+}
+
+fn testExp2() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@exp2(@as(ty, 2)) == 4);
+ try expect(math.approxEqAbs(ty, @exp2(@as(ty, 1.5)), 2.8284271247462, eps));
+ try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @exp2(v);
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log" {
+ // Old musl (and glibc?), and our current math.ln implementation do not return 1
+ // so also accept those values.
+ comptime try testLog();
+ try testLog();
+}
+
+fn testLog() !void {
+ {
+ var a: f16 = e;
+ try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
+ }
+ {
+ var a: f32 = e;
+ try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
+ }
+ {
+ var a: f64 = e;
+ try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
+ }
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(math.approxEqAbs(ty, @log(@as(ty, 2)), 0.6931471805599, eps));
+ try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log(v);
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log2" {
+ comptime try testLog2();
+ try testLog2();
+}
+
+fn testLog2() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@log2(@as(ty, 4)) == 2);
+ try expect(math.approxEqAbs(ty, @log2(@as(ty, 6)), 2.5849625007212, eps));
+ try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log2(v);
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@log10" {
+ comptime try testLog10();
+ try testLog10();
+}
+
+fn testLog10() !void {
+ inline for ([_]type{ f16, f32, f64 }) |ty| {
+ const eps = epsForType(ty);
+ try expect(@log10(@as(ty, 100)) == 2);
+ try expect(math.approxEqAbs(ty, @log10(@as(ty, 15)), 1.176091259056, eps));
+ try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps));
+ }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
+ var result = @log10(v);
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
+ }
+}
+
+test "@fabs" {
+ comptime try testFabs();
+ try testFabs();
+}
+
+fn testFabs() !void {
+ try expect(@fabs(@as(f16, -2.5)) == 2.5);
+ try expect(@fabs(@as(f16, 2.5)) == 2.5);
+ try expect(@fabs(@as(f32, -2.5)) == 2.5);
+ try expect(@fabs(@as(f32, 2.5)) == 2.5);
+ try expect(@fabs(@as(f64, -2.5)) == 2.5);
+ try expect(@fabs(@as(f64, 2.5)) == 2.5);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = -2.5;
+ // var b: f80 = 2.5;
+ // try expect(@fabs(a) == 2.5);
+ // try expect(@fabs(b) == 2.5);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @fabs(v);
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@floor" {
+ comptime try testFloor();
+ try testFloor();
+}
+
+fn testFloor() !void {
+ try expect(@floor(@as(f16, 2.1)) == 2);
+ try expect(@floor(@as(f32, 2.1)) == 2);
+ try expect(@floor(@as(f64, 3.5)) == 3);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = 3.5;
+ // try expect(@floor(a) == 3);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @floor(v);
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@ceil" {
+ comptime try testCeil();
+ try testCeil();
+}
+
+fn testCeil() !void {
+ try expect(@ceil(@as(f16, 2.1)) == 3);
+ try expect(@ceil(@as(f32, 2.1)) == 3);
+ try expect(@ceil(@as(f64, 3.5)) == 4);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = 3.5;
+ // try expect(@ceil(a) == 4);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @ceil(v);
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
+ }
+}
+
+test "@trunc" {
+ comptime try testTrunc();
+ try testTrunc();
+}
+
+fn testTrunc() !void {
+ try expect(@trunc(@as(f16, 2.1)) == 2);
+ try expect(@trunc(@as(f32, 2.1)) == 2);
+ try expect(@trunc(@as(f64, -3.5)) == -3);
+
+ // TODO test f128, and c_longdouble
+ // https://github.com/ziglang/zig/issues/4026
+ // {
+ // var a: f80 = -3.5;
+ // try expect(@trunc(a) == -3);
+ // }
+
+ // TODO: Implement Vector support for other backends
+ if (builtin.zig_backend == .stage1) {
+ var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
+ var result = @trunc(v);
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
+ try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
+ }
+}