From d5e99cc05ea05d701adffce55defc512d75e10d1 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Tue, 24 Apr 2018 19:18:31 +1200 Subject: Add initial complex-number support - Library type instead of builtin - All C complex functions implemented Partial WIP: Needs more tests for edge cases. --- std/math/complex/index.zig | 172 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 std/math/complex/index.zig (limited to 'std/math/complex/index.zig') diff --git a/std/math/complex/index.zig b/std/math/complex/index.zig new file mode 100644 index 0000000000..24f726453f --- /dev/null +++ b/std/math/complex/index.zig @@ -0,0 +1,172 @@ +const std = @import("../../index.zig"); +const debug = std.debug; +const math = std.math; + +pub const abs = @import("abs.zig").abs; +pub const acosh = @import("acosh.zig").acosh; +pub const acos = @import("acos.zig").acos; +pub const arg = @import("arg.zig").arg; +pub const asinh = @import("asinh.zig").asinh; +pub const asin = @import("asin.zig").asin; +pub const atanh = @import("atanh.zig").atanh; +pub const atan = @import("atan.zig").atan; +pub const conj = @import("conj.zig").conj; +pub const cosh = @import("cosh.zig").cosh; +pub const cos = @import("cos.zig").cos; +pub const exp = @import("exp.zig").exp; +pub const log = @import("log.zig").log; +pub const pow = @import("pow.zig").pow; +pub const proj = @import("proj.zig").proj; +pub const sinh = @import("sinh.zig").sinh; +pub const sin = @import("sin.zig").sin; +pub const sqrt = @import("sqrt.zig").sqrt; +pub const tanh = @import("tanh.zig").tanh; +pub const tan = @import("tan.zig").tan; + +// NOTE: Make this a builtin at some point? +pub fn Complex(comptime T: type) type { + return struct { + const Self = this; + + re: T, + im: T, + + pub fn new(re: T, im: T) Self { + return Self { + .re = re, + .im = im, + }; + } + + pub fn add(self: &const Self, other: &const Self) Self { + return Self { + .re = self.re + other.re, + .im = self.im + other.im, + }; + } + + pub fn sub(self: &const Self, other: &const Self) Self { + return Self { + .re = self.re - other.re, + .im = self.im - other.im, + }; + } + + pub fn mul(self: &const Self, other: &const Self) Self { + return Self { + .re = self.re * other.re - self.im * other.im, + .im = self.im * other.re + self.re * other.im, + }; + } + + pub fn div(self: &const Self, other: &const Self) Self { + const re_num = self.re * other.re + self.im * other.im; + const im_num = self.im * other.re - self.re * other.im; + const den = other.re * other.re + other.im * other.im; + + return Self { + .re = re_num / den, + .im = im_num / den, + }; + } + + pub fn conjugate(self: &const Self) Self { + return Self { + .re = self.re, + .im = -self.im, + }; + } + + pub fn reciprocal(self: &const Self) Self { + const m = self.re * self.re + self.im * self.im; + return Self { + .re = self.re / m, + .im = -self.im / m, + }; + } + + pub fn magnitude(self: &const Self) T { + return math.sqrt(self.re * self.re + self.im * self.im); + } + }; +} + +const epsilon = 0.0001; + +test "complex.add" { + const a = Complex(f32).new(5, 3); + const b = Complex(f32).new(2, 7); + const c = a.add(b); + + debug.assert(c.re == 7 and c.im == 10); +} + +test "complex.sub" { + const a = Complex(f32).new(5, 3); + const b = Complex(f32).new(2, 7); + const c = a.sub(b); + + debug.assert(c.re == 3 and c.im == -4); +} + +test "complex.mul" { + const a = Complex(f32).new(5, 3); + const b = Complex(f32).new(2, 7); + const c = a.mul(b); + + debug.assert(c.re == -11 and c.im == 41); +} + +test "complex.div" { + const a = Complex(f32).new(5, 3); + const b = Complex(f32).new(2, 7); + const c = a.div(b); + + debug.assert(math.approxEq(f32, c.re, f32(31)/53, epsilon) and + math.approxEq(f32, c.im, f32(-29)/53, epsilon)); +} + +test "complex.conjugate" { + const a = Complex(f32).new(5, 3); + const c = a.conjugate(); + + debug.assert(c.re == 5 and c.im == -3); +} + +test "complex.reciprocal" { + const a = Complex(f32).new(5, 3); + const c = a.reciprocal(); + + debug.assert(math.approxEq(f32, c.re, f32(5)/34, epsilon) and + math.approxEq(f32, c.im, f32(-3)/34, epsilon)); +} + +test "complex.magnitude" { + const a = Complex(f32).new(5, 3); + const c = a.magnitude(); + + debug.assert(math.approxEq(f32, c, 5.83095, epsilon)); +} + +test "complex.cmath" { + _ = @import("abs.zig"); + _ = @import("acosh.zig"); + _ = @import("acos.zig"); + _ = @import("arg.zig"); + _ = @import("asinh.zig"); + _ = @import("asin.zig"); + _ = @import("atanh.zig"); + _ = @import("atan.zig"); + _ = @import("conj.zig"); + _ = @import("cosh.zig"); + _ = @import("cos.zig"); + _ = @import("exp.zig"); + _ = @import("log.zig"); + _ = @import("pow.zig"); + _ = @import("proj.zig"); + _ = @import("sinh.zig"); + _ = @import("sin.zig"); + _ = @import("sqrt.zig"); + _ = @import("tanh.zig"); + _ = @import("tan.zig"); +} -- cgit v1.2.3 From 84391af7b8951735ec4719a6495ac37c032a1e36 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 24 Apr 2018 21:23:03 -0400 Subject: convert NOTE to TODO so we catch it later See #363 For Complex as a builtin type, see discussion in #949 --- std/math/complex/index.zig | 1 - std/math/complex/sqrt.zig | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'std/math/complex/index.zig') diff --git a/std/math/complex/index.zig b/std/math/complex/index.zig index 24f726453f..a4d493307e 100644 --- a/std/math/complex/index.zig +++ b/std/math/complex/index.zig @@ -23,7 +23,6 @@ pub const sqrt = @import("sqrt.zig").sqrt; pub const tanh = @import("tanh.zig").tanh; pub const tan = @import("tan.zig").tan; -// NOTE: Make this a builtin at some point? pub fn Complex(comptime T: type) type { return struct { const Self = this; diff --git a/std/math/complex/sqrt.zig b/std/math/complex/sqrt.zig index 02e6390572..afda69f7c9 100644 --- a/std/math/complex/sqrt.zig +++ b/std/math/complex/sqrt.zig @@ -4,8 +4,7 @@ const math = std.math; const cmath = math.complex; const Complex = cmath.Complex; -// NOTE: Returning @typeOf(z) here causes issues when trying to access the value. This is -// why we currently assign re, im parts to a new value explicitly for all tests. +// TODO when #733 is solved this can be @typeOf(z) instead of Complex(@typeOf(z.re)) pub fn sqrt(z: var) Complex(@typeOf(z.re)) { const T = @typeOf(z.re); -- cgit v1.2.3