master
1const std = @import("../std.zig");
2const testing = std.testing;
3const math = std.math;
4
5pub const abs = @import("complex/abs.zig").abs;
6pub const acosh = @import("complex/acosh.zig").acosh;
7pub const acos = @import("complex/acos.zig").acos;
8pub const arg = @import("complex/arg.zig").arg;
9pub const asinh = @import("complex/asinh.zig").asinh;
10pub const asin = @import("complex/asin.zig").asin;
11pub const atanh = @import("complex/atanh.zig").atanh;
12pub const atan = @import("complex/atan.zig").atan;
13pub const conj = @import("complex/conj.zig").conj;
14pub const cosh = @import("complex/cosh.zig").cosh;
15pub const cos = @import("complex/cos.zig").cos;
16pub const exp = @import("complex/exp.zig").exp;
17pub const log = @import("complex/log.zig").log;
18pub const pow = @import("complex/pow.zig").pow;
19pub const proj = @import("complex/proj.zig").proj;
20pub const sinh = @import("complex/sinh.zig").sinh;
21pub const sin = @import("complex/sin.zig").sin;
22pub const sqrt = @import("complex/sqrt.zig").sqrt;
23pub const tanh = @import("complex/tanh.zig").tanh;
24pub const tan = @import("complex/tan.zig").tan;
25
26/// A complex number consisting of a real an imaginary part. T must be a floating-point value.
27pub fn Complex(comptime T: type) type {
28 return struct {
29 const Self = @This();
30
31 /// Real part.
32 re: T,
33
34 /// Imaginary part.
35 im: T,
36
37 /// Create a new Complex number from the given real and imaginary parts.
38 pub fn init(re: T, im: T) Self {
39 return Self{
40 .re = re,
41 .im = im,
42 };
43 }
44
45 /// Returns the sum of two complex numbers.
46 pub fn add(self: Self, other: Self) Self {
47 return Self{
48 .re = self.re + other.re,
49 .im = self.im + other.im,
50 };
51 }
52
53 /// Returns the subtraction of two complex numbers.
54 pub fn sub(self: Self, other: Self) Self {
55 return Self{
56 .re = self.re - other.re,
57 .im = self.im - other.im,
58 };
59 }
60
61 /// Returns the product of two complex numbers.
62 pub fn mul(self: Self, other: Self) Self {
63 return Self{
64 .re = self.re * other.re - self.im * other.im,
65 .im = self.im * other.re + self.re * other.im,
66 };
67 }
68
69 /// Returns the quotient of two complex numbers.
70 pub fn div(self: Self, other: Self) Self {
71 const re_num = self.re * other.re + self.im * other.im;
72 const im_num = self.im * other.re - self.re * other.im;
73 const den = other.re * other.re + other.im * other.im;
74
75 return Self{
76 .re = re_num / den,
77 .im = im_num / den,
78 };
79 }
80
81 /// Returns the complex conjugate of a number.
82 pub fn conjugate(self: Self) Self {
83 return Self{
84 .re = self.re,
85 .im = -self.im,
86 };
87 }
88
89 /// Returns the negation of a complex number.
90 pub fn neg(self: Self) Self {
91 return Self{
92 .re = -self.re,
93 .im = -self.im,
94 };
95 }
96
97 /// Returns the product of complex number and i=sqrt(-1)
98 pub fn mulbyi(self: Self) Self {
99 return Self{
100 .re = -self.im,
101 .im = self.re,
102 };
103 }
104
105 /// Returns the reciprocal of a complex number.
106 pub fn reciprocal(self: Self) Self {
107 const m = self.re * self.re + self.im * self.im;
108 return Self{
109 .re = self.re / m,
110 .im = -self.im / m,
111 };
112 }
113
114 /// Returns the magnitude of a complex number.
115 pub fn magnitude(self: Self) T {
116 return @sqrt(self.re * self.re + self.im * self.im);
117 }
118
119 pub fn squaredMagnitude(self: Self) T {
120 return self.re * self.re + self.im * self.im;
121 }
122 };
123}
124
125const epsilon = 0.0001;
126
127test "add" {
128 const a = Complex(f32).init(5, 3);
129 const b = Complex(f32).init(2, 7);
130 const c = a.add(b);
131
132 try testing.expect(c.re == 7 and c.im == 10);
133}
134
135test "sub" {
136 const a = Complex(f32).init(5, 3);
137 const b = Complex(f32).init(2, 7);
138 const c = a.sub(b);
139
140 try testing.expect(c.re == 3 and c.im == -4);
141}
142
143test "mul" {
144 const a = Complex(f32).init(5, 3);
145 const b = Complex(f32).init(2, 7);
146 const c = a.mul(b);
147
148 try testing.expect(c.re == -11 and c.im == 41);
149}
150
151test "div" {
152 const a = Complex(f32).init(5, 3);
153 const b = Complex(f32).init(2, 7);
154 const c = a.div(b);
155
156 try testing.expect(math.approxEqAbs(f32, c.re, @as(f32, 31) / 53, epsilon) and
157 math.approxEqAbs(f32, c.im, @as(f32, -29) / 53, epsilon));
158}
159
160test "conjugate" {
161 const a = Complex(f32).init(5, 3);
162 const c = a.conjugate();
163
164 try testing.expect(c.re == 5 and c.im == -3);
165}
166
167test "neg" {
168 const a = Complex(f32).init(5, 3);
169 const c = a.neg();
170
171 try testing.expect(c.re == -5 and c.im == -3);
172}
173
174test "mulbyi" {
175 const a = Complex(f32).init(5, 3);
176 const c = a.mulbyi();
177
178 try testing.expect(c.re == -3 and c.im == 5);
179}
180
181test "reciprocal" {
182 const a = Complex(f32).init(5, 3);
183 const c = a.reciprocal();
184
185 try testing.expect(math.approxEqAbs(f32, c.re, @as(f32, 5) / 34, epsilon) and
186 math.approxEqAbs(f32, c.im, @as(f32, -3) / 34, epsilon));
187}
188
189test "magnitude" {
190 const a = Complex(f32).init(5, 3);
191 const c = a.magnitude();
192
193 try testing.expect(math.approxEqAbs(f32, c, 5.83095, epsilon));
194}
195
196test "squaredMagnitude" {
197 const a = Complex(f32).init(5, 3);
198 const c = a.squaredMagnitude();
199
200 try testing.expect(math.approxEqAbs(f32, c, math.pow(f32, a.magnitude(), 2), epsilon));
201}
202
203test {
204 _ = @import("complex/abs.zig");
205 _ = @import("complex/acosh.zig");
206 _ = @import("complex/acos.zig");
207 _ = @import("complex/arg.zig");
208 _ = @import("complex/asinh.zig");
209 _ = @import("complex/asin.zig");
210 _ = @import("complex/atanh.zig");
211 _ = @import("complex/atan.zig");
212 _ = @import("complex/conj.zig");
213 _ = @import("complex/cosh.zig");
214 _ = @import("complex/cos.zig");
215 _ = @import("complex/exp.zig");
216 _ = @import("complex/log.zig");
217 _ = @import("complex/pow.zig");
218 _ = @import("complex/proj.zig");
219 _ = @import("complex/sinh.zig");
220 _ = @import("complex/sin.zig");
221 _ = @import("complex/sqrt.zig");
222 _ = @import("complex/tanh.zig");
223 _ = @import("complex/tan.zig");
224}