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.FloatBuffer; 040 041 /** 042 * A complex value with float precision. 043 * 044 * @author Mikio L. Braun 045 * 046 */ 047 public class ComplexFloat { 048 049 private float r, i; 050 public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f); 051 public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f); 052 public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f); 053 public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f); 054 public static final ComplexFloat ZERO = new ComplexFloat(0.0f); 055 056 public ComplexFloat(float real, float imag) { 057 r = real; 058 i = imag; 059 } 060 061 public ComplexFloat(float real) { 062 this(real, 0.0f); 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 ComplexFloat set(float real, float imag) { 074 r = real; 075 i = imag; 076 return this; 077 } 078 079 public float real() { 080 return r; 081 } 082 083 public float imag() { 084 return i; 085 } 086 087 public ComplexFloat dup() { 088 return new ComplexFloat(r, i); 089 } 090 091 public ComplexFloat copy(ComplexFloat other) { 092 r = other.r; 093 i = other.i; 094 return this; 095 } 096 097 /** Add two complex numbers in-place */ 098 public ComplexFloat addi(ComplexFloat c, ComplexFloat 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 ComplexFloat addi(ComplexFloat c) { 111 return addi(c, this); 112 } 113 114 /** Add two complex numbers. */ 115 public ComplexFloat add(ComplexFloat c) { 116 return dup().addi(c); 117 } 118 119 /** Add a real number to a complex number in-place. */ 120 public ComplexFloat addi(float a, ComplexFloat 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 ComplexFloat addi(float c) { 132 return addi(c, this); 133 } 134 135 /** Add a real number to a complex number. */ 136 public ComplexFloat add(float c) { 137 return dup().addi(c); 138 } 139 140 /** Subtract two complex numbers, in-place */ 141 public ComplexFloat subi(ComplexFloat c, ComplexFloat 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 ComplexFloat subi(ComplexFloat c) { 153 return subi(c, this); 154 } 155 156 /** Subtract two complex numbers */ 157 public ComplexFloat sub(ComplexFloat c) { 158 return dup().subi(c); 159 } 160 161 public ComplexFloat subi(float a, ComplexFloat 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 ComplexFloat subi(float a) { 172 return subi(a, this); 173 } 174 175 public ComplexFloat sub(float r) { 176 return dup().subi(r); 177 } 178 179 /** Multiply two complex numbers, inplace */ 180 public ComplexFloat muli(ComplexFloat c, ComplexFloat result) { 181 float newR = r * c.r - i * c.i; 182 float newI = r * c.i + i * c.r; 183 result.r = newR; 184 result.i = newI; 185 return result; 186 } 187 188 public ComplexFloat muli(ComplexFloat c) { 189 return muli(c, this); 190 } 191 192 /** Multiply two complex numbers */ 193 public ComplexFloat mul(ComplexFloat c) { 194 return dup().muli(c); 195 } 196 197 public ComplexFloat mul(float v) { 198 return dup().muli(v); 199 } 200 201 public ComplexFloat muli(float v, ComplexFloat 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 ComplexFloat muli(float v) { 213 return muli(v, this); 214 } 215 216 /** Divide two complex numbers */ 217 public ComplexFloat div(ComplexFloat c) { 218 return dup().divi(c); 219 } 220 221 /** Divide two complex numbers, in-place */ 222 public ComplexFloat divi(ComplexFloat c, ComplexFloat result) { 223 float d = c.r * c.r + c.i * c.i; 224 float newR = (r * c.r + i * c.i) / d; 225 float newI = (i * c.r - r * c.i) / d; 226 result.r = newR; 227 result.i = newI; 228 return result; 229 } 230 231 public ComplexFloat divi(ComplexFloat c) { 232 return divi(c, this); 233 } 234 235 public ComplexFloat divi(float v, ComplexFloat 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 ComplexFloat divi(float v) { 247 return divi(v, this); 248 } 249 250 public ComplexFloat div(float v) { 251 return dup().divi(v); 252 } 253 254 /** Return the absolute value */ 255 public float abs() { 256 return (float) Math.sqrt(r * r + i * i); 257 } 258 259 /** Returns the argument of a complex number. */ 260 public float arg() { 261 return (float) Math.acos(r/abs()); 262 } 263 264 public ComplexFloat invi() { 265 float d = r * r + i * i; 266 r = r / d; 267 i = -i / d; 268 return this; 269 } 270 271 public ComplexFloat inv() { 272 return dup().invi(); 273 } 274 275 public ComplexFloat neg() { 276 return dup().negi(); 277 } 278 279 public ComplexFloat negi() { 280 r = -r; 281 i = -i; 282 return this; 283 } 284 285 public ComplexFloat conji() { 286 i = -i; 287 return this; 288 } 289 290 public ComplexFloat conj() { 291 return dup().conji(); 292 } 293 294 public ComplexFloat sqrt() { 295 float a = abs(); 296 float s2 = (float)Math.sqrt(2); 297 float p = (float)Math.sqrt(a + r)/s2; 298 float q = (float)Math.sqrt(a - r)/s2 * Math.signum(i); 299 return new ComplexFloat(p, q); 300 } 301 302 /** 303 * Comparing two DoubleComplex values. 304 */ 305 public boolean equals(Object o) { 306 if (!(o instanceof ComplexFloat)) { 307 return false; 308 } 309 ComplexFloat c = (ComplexFloat) o; 310 311 return eq(c); 312 } 313 314 public boolean eq(ComplexFloat c) { 315 return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6; 316 } 317 318 public boolean ne(ComplexFloat c) { 319 return !eq(c); 320 } 321 322 public boolean isZero() { 323 return r == 0.0f && i == 0.0f; 324 } 325 326 public boolean isReal() { 327 return i == 0.0f; 328 } 329 330 public boolean isImag() { 331 return r == 0.0f; 332 } 333 }