001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.lib.math; 011 012import ij.IJ; 013import imagingbook.lib.math.Complex; 014 015import java.awt.geom.Point2D; 016import java.util.Locale; 017 018public class Complex { 019 020 private final double re; 021 private final double im; 022 023 public double re() { 024 return this.re; 025 } 026 027 public double im() { 028 return this.im; 029 } 030 031 public Complex(double re, double im) { 032 this.re = re; 033 this.im = im; 034 } 035 036 public Complex(Point2D p) { 037 this.re = p.getX(); 038 this.im = p.getY(); 039 } 040 041 public Complex(Complex c) { 042 this.re = c.re; 043 this.im = c.im; 044 } 045 046 /* 047 * Create a complex quantity on the unit circle with angle 'phi'. 048 * e^{\i \phi} = \cos(\phi) + \i \cdot \sin(\phi) 049 */ 050 public Complex(double phi) { 051 this.re = Math.cos(phi); 052 this.im = Math.sin(phi); 053 } 054 055 public static Complex[] makeComplexVector(int M) { 056 Complex[] g = new Complex[M]; 057 for (int i = 0; i < M; i++) { 058 g[i] = new Complex(0, 0); 059 } 060 return g; 061 } 062 063 public static Complex[] duplicate(Complex[] g1) { 064 Complex[] g2 = new Complex[g1.length]; 065 for (int i = 0; i < g1.length; i++) { 066 g2[i] = new Complex(g1[i].re, g1[i].im); 067 } 068 return g2; 069 } 070 071 072 public static Complex[] makeComplexVector(double[] signal) { 073 int M = signal.length; 074 Complex[] g = new Complex[M]; 075 for (int i = 0; i < M; i++) { 076 g[i] = new Complex(signal[i], 0); 077 } 078 return g; 079 } 080 081 public static Complex[] makeComplexVector(double[] real, double[] imag) { 082 int M = real.length; 083 Complex[] g = new Complex[M]; 084 for (int i = 0; i < M; i++) { 085 g[i] = new Complex(real[i], imag[i]); 086 } 087 return g; 088 } 089 090 // radius 091 public double abs() { 092 return Math.sqrt(this.abs2()); 093 } 094 095 // squared radius 096 public double abs2() { 097 return re * re + im * im; 098 } 099 100 // angle 101 public double arg() { 102 return Math.atan2(im, re); 103 } 104 105 106 /* 107 * ---- complex arithmetic --------------- 108 */ 109 110 // complex conjugate 111 public Complex conjugate() { 112 return new Complex(this.re, -this.im); 113 } 114 115 public Complex add(Complex c2) { 116 return new Complex(this.re + c2.re, this.im + c2.im); 117 } 118 119 public Complex mult(double s) { 120 return new Complex(this.re * s, this.im * s); 121 } 122 123 public Complex mult(Complex c2) { 124 // (x1 + i y1)(x2 + i y2) = (x1 x2 + y1 y2) + i (x1 y2 + y1 x2) 125 Complex c1 = this; 126 double x = c1.re * c2.re - c1.im * c2.im; 127 double y = c1.re * c2.im + c1.im * c2.re; 128 return new Complex(x, y); 129 } 130 131 public Complex rotate(double phi) { 132 return this.mult(new Complex(phi)); 133 } 134 135 public double distance(Complex c2) { 136 Complex c1 = this; 137 double dRe = c1.re - c2.re; 138 double dIm = c1.im - c2.im; 139 return Math.sqrt(dRe*dRe + dIm*dIm); 140 } 141 142 public double crossProduct(Complex c2) { 143 Complex c1 = this; 144 return c1.re * c2.im - c1.im * c2.re; 145 } 146 147 public double dotProduct(Complex c2) { 148 Complex c1 = this; 149 return c1.re * c2.re + c1.im * c2.im; 150 } 151 152 public Complex exp(int k) { 153 if (k < 0) throw new IllegalArgumentException("exponent k >= 0 expected"); 154 Complex prod = new Complex(1, 0); 155 for (int i = 0; i < k; i++) { 156 prod = prod.mult(this); 157 } 158 return prod; 159 } 160 161 public String toString() { 162 if (this.im >= 0) { 163 return String.format(Locale.US, "(%.4f + %.4f i)", this.re, this.im); 164 } 165 else { 166 return String.format(Locale.US, "(%.4f - %.4f i)", this.re, Math.abs(this.im)); 167 } 168 } 169 170 // ------------------------------------------------------- 171 172 public static void printComplexVector(Complex[] g, String title) { 173 IJ.log("Listing of " + title); 174 for (int i = 0; i < g.length; i++) { 175 if (g[i] == null) 176 IJ.log(String.format("%d: ********", i)); 177 else { 178 double gr = g[i].re; 179 double gi = g[i].im; 180 if (gi >= 0) { 181 IJ.log(String.format(Locale.US, "%d: %6.2f + %6.2fi", i, gr, Math.abs(gi))); 182 } 183 else { 184 IJ.log(String.format(Locale.US, "%d: %6.2f - %6.2fi", i, gr, Math.abs(gi))); 185 } 186 } 187 } 188 } 189 190 191 //------------ TESTING only ------------------------------ 192 193 public static void main(String[] args) { 194 Complex z1 = new Complex(0.3, 0.6); 195 Complex z2 = new Complex(-1, 0.2); 196 System.out.println("z1 = " + z1); 197 System.out.println("z2 = " + z2); 198 Complex z3 = z1.mult(z2); 199 System.out.println("z3 = " + z3); 200 Complex z4 = z2.mult(z1); 201 System.out.println("z4 = " + z4); 202 } 203 204}