1 package org.djutils.complex;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotEquals;
6 import static org.junit.Assert.assertTrue;
7
8 import org.djutils.base.AngleUtil;
9 import org.junit.Test;
10
11
12
13
14
15
16
17
18
19
20
21 public class TestComplex
22 {
23
24
25
26
27 @Test
28 public void testConstructors()
29 {
30 double[] testValues = new double[] { 0, 1, 100, -1, -10000, Math.PI };
31
32 for (double re : testValues)
33 {
34 for (double im : testValues)
35 {
36 Complex complex = new Complex(re, im);
37 assertEquals("re", re, complex.re, 0.0001);
38 assertEquals("im", im, complex.im, 0.0001);
39 assertEquals("getRe", re, complex.getRe(), 0.0001);
40 assertEquals("getIm", im, complex.getIm(), 0.0001);
41 assertEquals("norm", Math.hypot(re, im), complex.norm(), 0.0001);
42 if (re != 0 || im != 0)
43 {
44 assertEquals("phi", Math.atan2(im, re), complex.phi(), 0.000001);
45 }
46 if (im == 0)
47 {
48 assertTrue("If imaginary part is 0; complex is pure real", complex.isReal());
49 complex = new Complex(re);
50 assertEquals("re", re, complex.re, 0.0001);
51 assertEquals("im", im, complex.im, 0.0001);
52 assertEquals("norm", Math.hypot(re, im), complex.norm(), 0.0001);
53 if (re != 0)
54 {
55 assertEquals("phi", Math.atan2(im, re), complex.phi(), 0.000001);
56 }
57 }
58 else
59 {
60 assertFalse("If imaginary part is not null; complex is not pure real", complex.isReal());
61 }
62 if (re == 0)
63 {
64 assertTrue("If real part is 0; complex is imaginary", complex.isImaginary());
65 }
66 else
67 {
68 assertFalse("If real part is not 0; comples is not imaginary", complex.isImaginary());
69 }
70 Complex conjugate = complex.conjugate();
71 assertEquals("Conjugate re", complex.re, conjugate.re, 0);
72 assertEquals("Conjugate im", -complex.im, conjugate.im, 0);
73 }
74 }
75 }
76
77
78
79
80 @Test
81 public void testConstants()
82 {
83 assertEquals("real component of ZERO", 0, Complex.ZERO.re, 0);
84 assertEquals("imaginary component of ZERO", 0, Complex.ZERO.im, 0);
85 assertEquals("real component of ONE", 1, Complex.ONE.re, 0);
86 assertEquals("imaginary component of ONE", 0, Complex.ONE.im, 0);
87 assertEquals("real component of MINUS_ONE", -1, Complex.MINUS_ONE.re, 0);
88 assertEquals("imaginary component of MINUS_ONE", 0, Complex.MINUS_ONE.im, 0);
89 assertEquals("real component of I", 0, Complex.I.re, 0);
90 assertEquals("imaginary component of I", 1, Complex.I.im, 0);
91 assertEquals("real component of MINUS_I", 0, Complex.MINUS_I.re, 0);
92 assertEquals("imaginary component of MINUS_I", -1, Complex.MINUS_I.im, 0);
93 }
94
95
96
97
98 @Test
99 public void testOperations()
100 {
101 Complex a = new Complex(12, -34);
102 Complex b = new Complex(-23, 45);
103 Complex c = a.plus(b);
104 assertEquals("sum re", a.re + b.re, c.re, 0.00001);
105 assertEquals("sum im", a.im + b.im, c.im, 0.00001);
106 c = a.plus(123);
107 assertEquals("sum re", a.re + 123, c.re, 0.00001);
108 assertEquals("sum im", a.im, c.im, 0.00001);
109 c = a.minus(b);
110 assertEquals("difference re", a.re - b.re, c.re, 0.00001);
111 assertEquals("difference im", a.im - b.im, c.im, 0.00001);
112 c = a.minus(123);
113 assertEquals("difference re", a.re - 123, c.re, 0.00001);
114 assertEquals("difference im", a.im, c.im, 0.00001);
115 c = a.times(b);
116 assertEquals("product norm", a.norm() * b.norm(), c.norm(), 0.0001);
117 assertEquals("product phi", a.phi() + b.phi(), c.phi(), 0.000001);
118 c = a.times(123);
119 assertEquals("product norm", a.norm() * 123, c.norm(), 0.0001);
120 assertEquals("product phi", a.phi(), c.phi(), 0.000001);
121 c = a.reciprocal();
122 assertEquals("norm of reciprocal", a.norm(), 1 / c.norm(), 0.00001);
123 assertEquals("phi of reciprocal", -a.phi(), c.phi(), 0.000001);
124 c = a.times(c);
125 assertEquals("a * a.reciprocal re", 1, c.re, 0.00001);
126 assertEquals("a * a.reciprocal im", 0, c.im, 0.00001);
127 for (double angle : new double[] { 0, 0.1, 1, Math.E, Math.PI, 5, 10, -1, -5 })
128 {
129 c = a.rotate(angle);
130 assertEquals("rotated a norm", a.norm(), c.norm(), 0.00001);
131 assertEquals("rotation difference", AngleUtil.normalizeAroundZero(a.phi() + angle), c.phi(), 0.000001);
132 }
133 c = a.divideBy(b);
134 assertEquals("norm of division", a.norm() / b.norm(), c.norm(), 0.0000001);
135 assertEquals("phi of division", AngleUtil.normalizeAroundZero(a.phi() - b.phi()), c.phi(), 0.000001);
136 c = a.divideBy(123);
137 assertEquals("dividend re", a.re / 123, c.re, 0.0000001);
138 assertEquals("dividend im", a.im / 123, c.im, 0.0000001);
139 c = Complex.ZERO.divideBy(Complex.ZERO);
140 assertTrue("ZERO / ZERO re is NaN", Double.isNaN(c.re));
141 assertTrue("ZERO / ZERO im is NaN", Double.isNaN(c.im));
142 c = Complex.ONE.divideBy(Complex.ZERO);
143 assertTrue("ONE / ZERO re is positive Infinity", Double.isInfinite(c.re) && c.re > 0);
144 assertTrue("ONE / ZERO im is NaN", Double.isNaN(c.im));
145 c = Complex.ZERO.minus(Complex.ONE).divideBy(Complex.ZERO);
146 assertTrue("minus ONE / ZERO re is negative Infinity", Double.isInfinite(c.re) && c.re < 0);
147 assertTrue("minus ONE / ZERO im is NaN", Double.isNaN(c.im));
148 c = Complex.I.divideBy(Complex.ZERO);
149 assertTrue("I / ZERO re is NaN", Double.isNaN(c.re));
150 assertTrue("I / ZERO im is positive Infinity", Double.isInfinite(c.im) && c.im > 0);
151 c = Complex.ZERO.minus(Complex.I).divideBy(Complex.ZERO);
152 assertTrue("minus I / ZERO re is NaN", Double.isNaN(c.re));
153 assertTrue("minus I / ZERO im is positive Infinity", Double.isInfinite(c.im) && c.im < 0);
154 c = Complex.ZERO.reciprocal();
155 assertTrue("reciprocal of ZERO re is positive Infinity ", Double.isInfinite(c.re) && c.re > 0);
156 assertTrue("reciprocal of ZERO im is positive Infinity ", Double.isInfinite(c.im) && c.im > 0);
157 c = Complex.ONE.divideBy(Complex.I);
158 assertEquals("ONE / I re is 0", 0, c.re, 0);
159 assertEquals("ONE / I im is -1", -1, c.im, 0);
160 c = Complex.ZERO.divideBy(0.0);
161 assertTrue("ZERO / 0.0 re is NaN", Double.isNaN(c.re));
162 assertTrue("ZERO / 0.0 im is NaN", Double.isNaN(c.im));
163 c = Complex.ONE.divideBy(0.0);
164 assertTrue("ONE / 0.0 re is positive Infinity", Double.isInfinite(c.re) && c.re > 0);
165 assertTrue("ONE / 0.0 im is NaN", Double.isNaN(c.im));
166 c = Complex.ZERO.minus(Complex.ONE).divideBy(0.0);
167 assertTrue("minus ONE / 0.0 re is negative Infinity", Double.isInfinite(c.re) && c.re < 0);
168 assertTrue("minus ONE / 0.0 im is NaN", Double.isNaN(c.im));
169 c = Complex.I.divideBy(0.0);
170 assertTrue("I / 0.0 re is NaN", Double.isNaN(c.re));
171 assertTrue("I / 0.0 im is positive Infinity", Double.isInfinite(c.im) && c.im > 0);
172 c = Complex.ZERO.minus(Complex.I).divideBy(0.0);
173 assertTrue("minus I / 0.0 re is NaN", Double.isNaN(c.re));
174 assertTrue("minus I / 0.0 im is positive Infinity", Double.isInfinite(c.im) && c.im < 0);
175 }
176
177
178
179
180 @SuppressWarnings({ "unlikely-arg-type" })
181 @Test
182 public void testOthers()
183 {
184 Complex a = new Complex(12, 34);
185 assertTrue("toString returns something descriptive", a.toString().startsWith("Complex "));
186 assertNotEquals("hashCode takes re into account", a.hashCode(), a.plus(Complex.ONE).hashCode());
187 assertNotEquals("hashCode takes im into account", a.hashCode(), a.plus(Complex.I).hashCode());
188 assertTrue(a.equals(a));
189 assertFalse(a.equals(null));
190 assertFalse(a.equals("This is a String; not a complex"));
191 assertFalse(a.equals(new Complex(12, 35)));
192 assertFalse(a.equals(new Complex(13, 34)));
193 assertEquals(a, new Complex(12, 34));
194 }
195
196
197
198
199 @Test
200 public void testHypot()
201 {
202 assertTrue("hypot(Inf, 0)", Double.isInfinite(Complex.hypot(Double.POSITIVE_INFINITY, 0)));
203 assertTrue("hypot(0, Inf)", Double.isInfinite(Complex.hypot(0, Double.POSITIVE_INFINITY)));
204 assertTrue("hypot(-Inf, 0)", Double.isInfinite(Complex.hypot(Double.NEGATIVE_INFINITY, 0)));
205 assertTrue("hypot(0, Inf)", Double.isInfinite(Complex.hypot(0, Double.NEGATIVE_INFINITY)));
206 assertEquals("hypot(0, 0)", 0, Complex.hypot(0, 0), 0);
207 assertTrue("hypot(Nan, 0)", Double.isNaN(Complex.hypot(Double.NaN, 0)));
208 assertTrue("hypot(0, Nan)", Double.isNaN(Complex.hypot(0, Double.NaN)));
209 assertTrue("hypot(Nan, Nan)", Double.isNaN(Complex.hypot(Double.NaN, Double.NaN)));
210 assertEquals("hypot(1, 1", Math.sqrt(2), Complex.hypot(1, 1), 0.000001);
211 assertEquals("hypot(Double.MAX_VALUE, 0)", Double.MAX_VALUE, Complex.hypot(Double.MAX_VALUE, 0),
212 Double.MAX_VALUE / 100000);
213 assertEquals("hypot(0, Double.MAX_VALUE)", Double.MAX_VALUE, Complex.hypot(0, Double.MAX_VALUE),
214 Double.MAX_VALUE / 100000);
215 assertEquals("hypot(Double.MIN_VALUE, 0)", Double.MIN_VALUE, Complex.hypot(Double.MIN_VALUE, 0), 0);
216 assertEquals("hypot(0, Double.MIN_VALUE)", Double.MIN_VALUE, Complex.hypot(0, Double.MIN_VALUE), 0);
217 assertEquals("hypot(Double.MAX_VALUE / 2, Double.MAX_VALUE / 2)", Double.MAX_VALUE / Math.sqrt(2),
218 Complex.hypot(Double.MAX_VALUE / 2, Double.MAX_VALUE / 2), Double.MAX_VALUE / 100000);
219 assertEquals("hypot(Double.MIN_VALUE * 10, Double.MIN_VALUE * 10)", Double.MIN_VALUE * 10 * Math.sqrt(2),
220 Complex.hypot(Double.MIN_VALUE * 10, Double.MIN_VALUE * 10), Double.MIN_VALUE);
221 assertEquals("hypot is symmetrical in x", Complex.hypot(10, 0), Complex.hypot(-10, 0), 0);
222 assertEquals("hypot is symmetrical in y", Complex.hypot(0, 10), Complex.hypot(0, -10), 0);
223 }
224
225 }