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 }