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 static java.lang.Math.sqrt;
040
041 import java.nio.FloatBuffer;
042
043 /**
044 * A complex value with float precision.
045 *
046 * @author Mikio L. Braun
047 *
048 */
049 public class ComplexFloat {
050
051 private float r, i;
052 public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f);
053 public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f);
054 public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f);
055 public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f);
056 public static final ComplexFloat ZERO = new ComplexFloat(0.0f);
057
058 public ComplexFloat(float real, float imag) {
059 r = real;
060 i = imag;
061 }
062
063 public ComplexFloat(float real) {
064 this(real, 0.0f);
065 }
066
067 public String toString() {
068 if (i >= 0) {
069 return r + " + " + i + "i";
070 } else {
071 return r + " - " + (-i) + "i";
072 }
073 }
074
075 public ComplexFloat set(float real, float imag) {
076 r = real;
077 i = imag;
078 return this;
079 }
080
081 public float real() {
082 return r;
083 }
084
085 public float imag() {
086 return i;
087 }
088
089 public ComplexFloat dup() {
090 return new ComplexFloat(r, i);
091 }
092
093 public ComplexFloat copy(ComplexFloat other) {
094 r = other.r;
095 i = other.i;
096 return this;
097 }
098
099 /** Add two complex numbers in-place */
100 public ComplexFloat addi(ComplexFloat c, ComplexFloat result) {
101 if (this == result) {
102 r += c.r;
103 i += c.i;
104 } else {
105 result.r = r + c.r;
106 result.i = i + c.i;
107 }
108 return result;
109 }
110
111 /** Add two complex numbers in-place storing the result in this. */
112 public ComplexFloat addi(ComplexFloat c) {
113 return addi(c, this);
114 }
115
116 /** Add two complex numbers. */
117 public ComplexFloat add(ComplexFloat c) {
118 return dup().addi(c);
119 }
120
121 /** Add a real number to a complex number in-place. */
122 public ComplexFloat addi(float a, ComplexFloat result) {
123 if (this == result) {
124 r += a;
125 } else {
126 result.r = r + a;
127 result.i = i;
128 }
129 return result;
130 }
131
132 /** Add a real number to complex number in-place, storing the result in this. */
133 public ComplexFloat addi(float c) {
134 return addi(c, this);
135 }
136
137 /** Add a real number to a complex number. */
138 public ComplexFloat add(float c) {
139 return dup().addi(c);
140 }
141
142 /** Subtract two complex numbers, in-place */
143 public ComplexFloat subi(ComplexFloat c, ComplexFloat result) {
144 if (this == result) {
145 r -= c.r;
146 i -= c.i;
147 } else {
148 result.r = r - c.r;
149 result.i = i - c.i;
150 }
151 return this;
152 }
153
154 public ComplexFloat subi(ComplexFloat c) {
155 return subi(c, this);
156 }
157
158 /** Subtract two complex numbers */
159 public ComplexFloat sub(ComplexFloat c) {
160 return dup().subi(c);
161 }
162
163 public ComplexFloat subi(float a, ComplexFloat result) {
164 if (this == result) {
165 r -= a;
166 } else {
167 result.r = r - a;
168 result.i = i;
169 }
170 return result;
171 }
172
173 public ComplexFloat subi(float a) {
174 return subi(a, this);
175 }
176
177 public ComplexFloat sub(float r) {
178 return dup().subi(r);
179 }
180
181 /** Multiply two complex numbers, inplace */
182 public ComplexFloat muli(ComplexFloat c, ComplexFloat result) {
183 float newR = r * c.r - i * c.i;
184 float newI = r * c.i + i * c.r;
185 result.r = newR;
186 result.i = newI;
187 return result;
188 }
189
190 public ComplexFloat muli(ComplexFloat c) {
191 return muli(c, this);
192 }
193
194 /** Multiply two complex numbers */
195 public ComplexFloat mul(ComplexFloat c) {
196 return dup().muli(c);
197 }
198
199 public ComplexFloat mul(float v) {
200 return dup().muli(v);
201 }
202
203 public ComplexFloat muli(float v, ComplexFloat result) {
204 if (this == result) {
205 r *= v;
206 i *= v;
207 } else {
208 result.r = r * v;
209 result.i = i * v;
210 }
211 return this;
212 }
213
214 public ComplexFloat muli(float v) {
215 return muli(v, this);
216 }
217
218 /** Divide two complex numbers */
219 public ComplexFloat div(ComplexFloat c) {
220 return dup().divi(c);
221 }
222
223 /** Divide two complex numbers, in-place */
224 public ComplexFloat divi(ComplexFloat c, ComplexFloat result) {
225 float d = c.r * c.r + c.i * c.i;
226 float newR = (r * c.r + i * c.i) / d;
227 float newI = (i * c.r - r * c.i) / d;
228 result.r = newR;
229 result.i = newI;
230 return result;
231 }
232
233 public ComplexFloat divi(ComplexFloat c) {
234 return divi(c, this);
235 }
236
237 public ComplexFloat divi(float v, ComplexFloat result) {
238 if (this == result) {
239 r /= v;
240 i /= v;
241 } else {
242 result.r = r / v;
243 result.i = i / v;
244 }
245 return this;
246 }
247
248 public ComplexFloat divi(float v) {
249 return divi(v, this);
250 }
251
252 public ComplexFloat div(float v) {
253 return dup().divi(v);
254 }
255
256 /** Return the absolute value */
257 public float abs() {
258 return (float) sqrt(r * r + i * i);
259 }
260
261 public ComplexFloat invi() {
262 float d = r * r + i * i;
263 r = r / d;
264 i = -i / d;
265 return this;
266 }
267
268 public ComplexFloat inv() {
269 return dup().invi();
270 }
271
272 public ComplexFloat neg() {
273 return dup().negi();
274 }
275
276 public ComplexFloat negi() {
277 r = -r;
278 i = -i;
279 return this;
280 }
281
282 public ComplexFloat conji() {
283 i = -i;
284 return this;
285 }
286
287 public ComplexFloat conj() {
288 return dup().conji();
289 }
290
291 /**
292 * Comparing two DoubleComplex values.
293 */
294 public boolean equals(Object o) {
295 if (!(o instanceof ComplexFloat)) {
296 return false;
297 }
298 ComplexFloat c = (ComplexFloat) o;
299
300 return eq(c);
301 }
302
303 public boolean eq(ComplexFloat c) {
304 return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6;
305 }
306
307 public boolean ne(ComplexFloat c) {
308 return !eq(c);
309 }
310
311 public boolean isZero() {
312 return r == 0.0f && i == 0.0f;
313 }
314
315 public boolean isReal() {
316 return i == 0.0f;
317 }
318
319 public boolean isImag() {
320 return r == 0.0f;
321 }
322 }