001 // --- BEGIN LICENSE BLOCK ---
002 /*
003 * Copyright (c) 2009, Mikio L. Braun
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are
008 * met:
009 *
010 * * Redistributions of source code must retain the above copyright
011 * notice, this list of conditions and the following disclaimer.
012 *
013 * * Redistributions in binary form must reproduce the above
014 * copyright notice, this list of conditions and the following
015 * disclaimer in the documentation and/or other materials provided
016 * with the distribution.
017 *
018 * * Neither the name of the Technische Universit?t Berlin nor the
019 * names of its contributors may be used to endorse or promote
020 * products derived from this software without specific prior
021 * written permission.
022 *
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
026 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
027 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
034 */
035 // --- END LICENSE BLOCK ---
036
037 package org.jblas;
038
039 import java.nio.DoubleBuffer;
040
041 /**
042 * A complex value with double precision.
043 *
044 * @author Mikio L. Braun
045 *
046 */
047 public class ComplexDouble {
048
049 private double r, i;
050 public static final ComplexDouble UNIT = new ComplexDouble(1.0, 0.0);
051 public static final ComplexDouble I = new ComplexDouble(0.0, 1.0);
052 public static final ComplexDouble NEG_UNIT = new ComplexDouble(-1.0, 0.0);
053 public static final ComplexDouble NEG_I = new ComplexDouble(0.0, -1.0);
054 public static final ComplexDouble ZERO = new ComplexDouble(0.0);
055
056 public ComplexDouble(double real, double imag) {
057 r = real;
058 i = imag;
059 }
060
061 public ComplexDouble(double real) {
062 this(real, 0.0);
063 }
064
065 public String toString() {
066 if (i >= 0) {
067 return r + " + " + i + "i";
068 } else {
069 return r + " - " + (-i) + "i";
070 }
071 }
072
073 public ComplexDouble set(double real, double imag) {
074 r = real;
075 i = imag;
076 return this;
077 }
078
079 public double real() {
080 return r;
081 }
082
083 public double imag() {
084 return i;
085 }
086
087 public ComplexDouble dup() {
088 return new ComplexDouble(r, i);
089 }
090
091 public ComplexDouble copy(ComplexDouble other) {
092 r = other.r;
093 i = other.i;
094 return this;
095 }
096
097 /** Add two complex numbers in-place */
098 public ComplexDouble addi(ComplexDouble c, ComplexDouble result) {
099 if (this == result) {
100 r += c.r;
101 i += c.i;
102 } else {
103 result.r = r + c.r;
104 result.i = i + c.i;
105 }
106 return result;
107 }
108
109 /** Add two complex numbers in-place storing the result in this. */
110 public ComplexDouble addi(ComplexDouble c) {
111 return addi(c, this);
112 }
113
114 /** Add two complex numbers. */
115 public ComplexDouble add(ComplexDouble c) {
116 return dup().addi(c);
117 }
118
119 /** Add a real number to a complex number in-place. */
120 public ComplexDouble addi(double a, ComplexDouble result) {
121 if (this == result) {
122 r += a;
123 } else {
124 result.r = r + a;
125 result.i = i;
126 }
127 return result;
128 }
129
130 /** Add a real number to complex number in-place, storing the result in this. */
131 public ComplexDouble addi(double c) {
132 return addi(c, this);
133 }
134
135 /** Add a real number to a complex number. */
136 public ComplexDouble add(double c) {
137 return dup().addi(c);
138 }
139
140 /** Subtract two complex numbers, in-place */
141 public ComplexDouble subi(ComplexDouble c, ComplexDouble result) {
142 if (this == result) {
143 r -= c.r;
144 i -= c.i;
145 } else {
146 result.r = r - c.r;
147 result.i = i - c.i;
148 }
149 return this;
150 }
151
152 public ComplexDouble subi(ComplexDouble c) {
153 return subi(c, this);
154 }
155
156 /** Subtract two complex numbers */
157 public ComplexDouble sub(ComplexDouble c) {
158 return dup().subi(c);
159 }
160
161 public ComplexDouble subi(double a, ComplexDouble result) {
162 if (this == result) {
163 r -= a;
164 } else {
165 result.r = r - a;
166 result.i = i;
167 }
168 return result;
169 }
170
171 public ComplexDouble subi(double a) {
172 return subi(a, this);
173 }
174
175 public ComplexDouble sub(double r) {
176 return dup().subi(r);
177 }
178
179 /** Multiply two complex numbers, inplace */
180 public ComplexDouble muli(ComplexDouble c, ComplexDouble result) {
181 double newR = r * c.r - i * c.i;
182 double newI = r * c.i + i * c.r;
183 result.r = newR;
184 result.i = newI;
185 return result;
186 }
187
188 public ComplexDouble muli(ComplexDouble c) {
189 return muli(c, this);
190 }
191
192 /** Multiply two complex numbers */
193 public ComplexDouble mul(ComplexDouble c) {
194 return dup().muli(c);
195 }
196
197 public ComplexDouble mul(double v) {
198 return dup().muli(v);
199 }
200
201 public ComplexDouble muli(double v, ComplexDouble result) {
202 if (this == result) {
203 r *= v;
204 i *= v;
205 } else {
206 result.r = r * v;
207 result.i = i * v;
208 }
209 return this;
210 }
211
212 public ComplexDouble muli(double v) {
213 return muli(v, this);
214 }
215
216 /** Divide two complex numbers */
217 public ComplexDouble div(ComplexDouble c) {
218 return dup().divi(c);
219 }
220
221 /** Divide two complex numbers, in-place */
222 public ComplexDouble divi(ComplexDouble c, ComplexDouble result) {
223 double d = c.r * c.r + c.i * c.i;
224 double newR = (r * c.r + i * c.i) / d;
225 double newI = (i * c.r - r * c.i) / d;
226 result.r = newR;
227 result.i = newI;
228 return result;
229 }
230
231 public ComplexDouble divi(ComplexDouble c) {
232 return divi(c, this);
233 }
234
235 public ComplexDouble divi(double v, ComplexDouble result) {
236 if (this == result) {
237 r /= v;
238 i /= v;
239 } else {
240 result.r = r / v;
241 result.i = i / v;
242 }
243 return this;
244 }
245
246 public ComplexDouble divi(double v) {
247 return divi(v, this);
248 }
249
250 public ComplexDouble div(double v) {
251 return dup().divi(v);
252 }
253
254 /** Return the absolute value */
255 public double abs() {
256 return (double) Math.sqrt(r * r + i * i);
257 }
258
259 /** Returns the argument of a complex number. */
260 public double arg() {
261 return (double) Math.acos(r/abs());
262 }
263
264 public ComplexDouble invi() {
265 double d = r * r + i * i;
266 r = r / d;
267 i = -i / d;
268 return this;
269 }
270
271 public ComplexDouble inv() {
272 return dup().invi();
273 }
274
275 public ComplexDouble neg() {
276 return dup().negi();
277 }
278
279 public ComplexDouble negi() {
280 r = -r;
281 i = -i;
282 return this;
283 }
284
285 public ComplexDouble conji() {
286 i = -i;
287 return this;
288 }
289
290 public ComplexDouble conj() {
291 return dup().conji();
292 }
293
294 public ComplexDouble sqrt() {
295 double a = abs();
296 double s2 = (double)Math.sqrt(2);
297 double p = (double)Math.sqrt(a + r)/s2;
298 double q = (double)Math.sqrt(a - r)/s2 * Math.signum(i);
299 return new ComplexDouble(p, q);
300 }
301
302 /**
303 * Comparing two DoubleComplex values.
304 */
305 public boolean equals(Object o) {
306 if (!(o instanceof ComplexDouble)) {
307 return false;
308 }
309 ComplexDouble c = (ComplexDouble) o;
310
311 return eq(c);
312 }
313
314 public boolean eq(ComplexDouble c) {
315 return Math.abs(r - c.r) + Math.abs(i - c.i) < (double) 1e-6;
316 }
317
318 public boolean ne(ComplexDouble c) {
319 return !eq(c);
320 }
321
322 public boolean isZero() {
323 return r == 0.0 && i == 0.0;
324 }
325
326 public boolean isReal() {
327 return i == 0.0;
328 }
329
330 public boolean isImag() {
331 return r == 0.0;
332 }
333 }