aboutsummaryrefslogtreecommitdiff
path: root/lib/std/math/sin.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-26 01:54:45 -0400
committerGitHub <noreply@github.com>2019-09-26 01:54:45 -0400
commit68bb3945708c43109c48bda3664176307d45b62c (patch)
treeafb9731e10cef9d192560b52cd9ae2cf179775c4 /lib/std/math/sin.zig
parent6128bc728d1e1024a178c16c2149f5b1a167a013 (diff)
parent4637e8f9699af9c3c6cf4df50ef5bb67c7a318a4 (diff)
downloadzig-68bb3945708c43109c48bda3664176307d45b62c.tar.gz
zig-68bb3945708c43109c48bda3664176307d45b62c.zip
Merge pull request #3315 from ziglang/mv-std-lib
Move std/ to lib/std/
Diffstat (limited to 'lib/std/math/sin.zig')
-rw-r--r--lib/std/math/sin.zig150
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/std/math/sin.zig b/lib/std/math/sin.zig
new file mode 100644
index 0000000000..ee07b4f85e
--- /dev/null
+++ b/lib/std/math/sin.zig
@@ -0,0 +1,150 @@
+// Ported from go, which is licensed under a BSD-3 license.
+// https://golang.org/LICENSE
+//
+// https://golang.org/src/math/sin.go
+
+const builtin = @import("builtin");
+const std = @import("../std.zig");
+const math = std.math;
+const expect = std.testing.expect;
+
+/// Returns the sine of the radian value x.
+///
+/// Special Cases:
+/// - sin(+-0) = +-0
+/// - sin(+-inf) = nan
+/// - sin(nan) = nan
+pub fn sin(x: var) @typeOf(x) {
+ const T = @typeOf(x);
+ return switch (T) {
+ f32 => sin_(T, x),
+ f64 => sin_(T, x),
+ else => @compileError("sin not implemented for " ++ @typeName(T)),
+ };
+}
+
+// sin polynomial coefficients
+const S0 = 1.58962301576546568060E-10;
+const S1 = -2.50507477628578072866E-8;
+const S2 = 2.75573136213857245213E-6;
+const S3 = -1.98412698295895385996E-4;
+const S4 = 8.33333333332211858878E-3;
+const S5 = -1.66666666666666307295E-1;
+
+// cos polynomial coeffiecients
+const C0 = -1.13585365213876817300E-11;
+const C1 = 2.08757008419747316778E-9;
+const C2 = -2.75573141792967388112E-7;
+const C3 = 2.48015872888517045348E-5;
+const C4 = -1.38888888888730564116E-3;
+const C5 = 4.16666666666665929218E-2;
+
+const pi4a = 7.85398125648498535156e-1;
+const pi4b = 3.77489470793079817668E-8;
+const pi4c = 2.69515142907905952645E-15;
+const m4pi = 1.273239544735162542821171882678754627704620361328125;
+
+fn sin_(comptime T: type, x_: T) T {
+ const I = @IntType(true, T.bit_count);
+
+ var x = x_;
+ if (x == 0 or math.isNan(x)) {
+ return x;
+ }
+ if (math.isInf(x)) {
+ return math.nan(T);
+ }
+
+ var sign = x < 0;
+ x = math.fabs(x);
+
+ var y = math.floor(x * m4pi);
+ var j = @floatToInt(I, y);
+
+ if (j & 1 == 1) {
+ j += 1;
+ y += 1;
+ }
+
+ j &= 7;
+ if (j > 3) {
+ j -= 4;
+ sign = !sign;
+ }
+
+ const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
+ const w = z * z;
+
+ const r = if (j == 1 or j == 2)
+ 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))))
+ else
+ z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
+
+ return if (sign) -r else r;
+}
+
+test "math.sin" {
+ if (builtin.os == .linux and builtin.arch == .arm and builtin.abi == .musleabihf) {
+ // TODO https://github.com/ziglang/zig/issues/3289
+ return error.SkipZigTest;
+ }
+ expect(sin(f32(0.0)) == sin_(f32, 0.0));
+ expect(sin(f64(0.0)) == sin_(f64, 0.0));
+ expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
+}
+
+test "math.sin32" {
+ if (builtin.os == .linux and builtin.arch == .arm and builtin.abi == .musleabihf) {
+ // TODO https://github.com/ziglang/zig/issues/3289
+ return error.SkipZigTest;
+ }
+ const epsilon = 0.000001;
+
+ expect(math.approxEq(f32, sin_(f32, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 0.2), 0.198669, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 1.5), 0.997495, epsilon));
+ expect(math.approxEq(f32, sin_(f32, -1.5), -0.997495, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 37.45), -0.246544, epsilon));
+ expect(math.approxEq(f32, sin_(f32, 89.123), 0.916166, epsilon));
+}
+
+test "math.sin64" {
+ if (builtin.os == .linux and builtin.arch == .arm and builtin.abi == .musleabihf) {
+ // TODO https://github.com/ziglang/zig/issues/3289
+ return error.SkipZigTest;
+ }
+ const epsilon = 0.000001;
+
+ expect(math.approxEq(f64, sin_(f64, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 0.2), 0.198669, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 1.5), 0.997495, epsilon));
+ expect(math.approxEq(f64, sin_(f64, -1.5), -0.997495, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 37.45), -0.246543, epsilon));
+ expect(math.approxEq(f64, sin_(f64, 89.123), 0.916166, epsilon));
+}
+
+test "math.sin32.special" {
+ if (builtin.os == .linux and builtin.arch == .arm and builtin.abi == .musleabihf) {
+ // TODO https://github.com/ziglang/zig/issues/3289
+ return error.SkipZigTest;
+ }
+ expect(sin_(f32, 0.0) == 0.0);
+ expect(sin_(f32, -0.0) == -0.0);
+ expect(math.isNan(sin_(f32, math.inf(f32))));
+ expect(math.isNan(sin_(f32, -math.inf(f32))));
+ expect(math.isNan(sin_(f32, math.nan(f32))));
+}
+
+test "math.sin64.special" {
+ if (builtin.os == .linux and builtin.arch == .arm and builtin.abi == .musleabihf) {
+ // TODO https://github.com/ziglang/zig/issues/3289
+ return error.SkipZigTest;
+ }
+ expect(sin_(f64, 0.0) == 0.0);
+ expect(sin_(f64, -0.0) == -0.0);
+ expect(math.isNan(sin_(f64, math.inf(f64))));
+ expect(math.isNan(sin_(f64, -math.inf(f64))));
+ expect(math.isNan(sin_(f64, math.nan(f64))));
+}