View Javadoc
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   * TestComplex.java. <br>
13   * <br>
14   * Copyright (c) 2021-2022 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
15   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
16   * distributed under a three-clause BSD-style license, which can be found at
17   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. <br>
18   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19   * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20   */
21  public class TestComplex
22  {
23  
24      /**
25       * Test the various constructors of Complex.
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(); // Loss less operation; we can test for exact equality
71                  assertEquals("Conjugate re", complex.re, conjugate.re, 0);
72                  assertEquals("Conjugate im", -complex.im, conjugate.im, 0);
73              }
74          }
75      }
76  
77      /**
78       * Test the constants defined by the Complex class.
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       * Test the methods.
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      * Test other methods.
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      * Test the hypot method.
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 }