Complex.h (9492B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #ifndef __MATH_COMPLEX_H__ 30 #define __MATH_COMPLEX_H__ 31 32 /* 33 =============================================================================== 34 35 Complex number 36 37 =============================================================================== 38 */ 39 40 class idComplex { 41 public: 42 float r; // real part 43 float i; // imaginary part 44 45 idComplex(); 46 idComplex( const float r, const float i ); 47 48 void Set( const float r, const float i ); 49 void Zero(); 50 51 float operator[]( int index ) const; 52 float & operator[]( int index ); 53 54 idComplex operator-() const; 55 idComplex & operator=( const idComplex &a ); 56 57 idComplex operator*( const idComplex &a ) const; 58 idComplex operator/( const idComplex &a ) const; 59 idComplex operator+( const idComplex &a ) const; 60 idComplex operator-( const idComplex &a ) const; 61 62 idComplex & operator*=( const idComplex &a ); 63 idComplex & operator/=( const idComplex &a ); 64 idComplex & operator+=( const idComplex &a ); 65 idComplex & operator-=( const idComplex &a ); 66 67 idComplex operator*( const float a ) const; 68 idComplex operator/( const float a ) const; 69 idComplex operator+( const float a ) const; 70 idComplex operator-( const float a ) const; 71 72 idComplex & operator*=( const float a ); 73 idComplex & operator/=( const float a ); 74 idComplex & operator+=( const float a ); 75 idComplex & operator-=( const float a ); 76 77 friend idComplex operator*( const float a, const idComplex &b ); 78 friend idComplex operator/( const float a, const idComplex &b ); 79 friend idComplex operator+( const float a, const idComplex &b ); 80 friend idComplex operator-( const float a, const idComplex &b ); 81 82 bool Compare( const idComplex &a ) const; // exact compare, no epsilon 83 bool Compare( const idComplex &a, const float epsilon ) const; // compare with epsilon 84 bool operator==( const idComplex &a ) const; // exact compare, no epsilon 85 bool operator!=( const idComplex &a ) const; // exact compare, no epsilon 86 87 idComplex Reciprocal() const; 88 idComplex Sqrt() const; 89 float Abs() const; 90 91 int GetDimension() const; 92 93 const float * ToFloatPtr() const; 94 float * ToFloatPtr(); 95 const char * ToString( int precision = 2 ) const; 96 }; 97 98 extern idComplex complex_origin; 99 #define complex_zero complex_origin 100 101 ID_INLINE idComplex::idComplex() { 102 } 103 104 ID_INLINE idComplex::idComplex( const float r, const float i ) { 105 this->r = r; 106 this->i = i; 107 } 108 109 ID_INLINE void idComplex::Set( const float r, const float i ) { 110 this->r = r; 111 this->i = i; 112 } 113 114 ID_INLINE void idComplex::Zero() { 115 r = i = 0.0f; 116 } 117 118 ID_INLINE float idComplex::operator[]( int index ) const { 119 assert( index >= 0 && index < 2 ); 120 return ( &r )[ index ]; 121 } 122 123 ID_INLINE float& idComplex::operator[]( int index ) { 124 assert( index >= 0 && index < 2 ); 125 return ( &r )[ index ]; 126 } 127 128 ID_INLINE idComplex idComplex::operator-() const { 129 return idComplex( -r, -i ); 130 } 131 132 ID_INLINE idComplex &idComplex::operator=( const idComplex &a ) { 133 r = a.r; 134 i = a.i; 135 return *this; 136 } 137 138 ID_INLINE idComplex idComplex::operator*( const idComplex &a ) const { 139 return idComplex( r * a.r - i * a.i, i * a.r + r * a.i ); 140 } 141 142 ID_INLINE idComplex idComplex::operator/( const idComplex &a ) const { 143 float s, t; 144 if ( idMath::Fabs( a.r ) >= idMath::Fabs( a.i ) ) { 145 s = a.i / a.r; 146 t = 1.0f / ( a.r + s * a.i ); 147 return idComplex( ( r + s * i ) * t, ( i - s * r ) * t ); 148 } else { 149 s = a.r / a.i; 150 t = 1.0f / ( s * a.r + a.i ); 151 return idComplex( ( r * s + i ) * t, ( i * s - r ) * t ); 152 } 153 } 154 155 ID_INLINE idComplex idComplex::operator+( const idComplex &a ) const { 156 return idComplex( r + a.r, i + a.i ); 157 } 158 159 ID_INLINE idComplex idComplex::operator-( const idComplex &a ) const { 160 return idComplex( r - a.r, i - a.i ); 161 } 162 163 ID_INLINE idComplex &idComplex::operator*=( const idComplex &a ) { 164 *this = idComplex( r * a.r - i * a.i, i * a.r + r * a.i ); 165 return *this; 166 } 167 168 ID_INLINE idComplex &idComplex::operator/=( const idComplex &a ) { 169 float s, t; 170 if ( idMath::Fabs( a.r ) >= idMath::Fabs( a.i ) ) { 171 s = a.i / a.r; 172 t = 1.0f / ( a.r + s * a.i ); 173 *this = idComplex( ( r + s * i ) * t, ( i - s * r ) * t ); 174 } else { 175 s = a.r / a.i; 176 t = 1.0f / ( s * a.r + a.i ); 177 *this = idComplex( ( r * s + i ) * t, ( i * s - r ) * t ); 178 } 179 return *this; 180 } 181 182 ID_INLINE idComplex &idComplex::operator+=( const idComplex &a ) { 183 r += a.r; 184 i += a.i; 185 return *this; 186 } 187 188 ID_INLINE idComplex &idComplex::operator-=( const idComplex &a ) { 189 r -= a.r; 190 i -= a.i; 191 return *this; 192 } 193 194 ID_INLINE idComplex idComplex::operator*( const float a ) const { 195 return idComplex( r * a, i * a ); 196 } 197 198 ID_INLINE idComplex idComplex::operator/( const float a ) const { 199 float s = 1.0f / a; 200 return idComplex( r * s, i * s ); 201 } 202 203 ID_INLINE idComplex idComplex::operator+( const float a ) const { 204 return idComplex( r + a, i ); 205 } 206 207 ID_INLINE idComplex idComplex::operator-( const float a ) const { 208 return idComplex( r - a, i ); 209 } 210 211 ID_INLINE idComplex &idComplex::operator*=( const float a ) { 212 r *= a; 213 i *= a; 214 return *this; 215 } 216 217 ID_INLINE idComplex &idComplex::operator/=( const float a ) { 218 float s = 1.0f / a; 219 r *= s; 220 i *= s; 221 return *this; 222 } 223 224 ID_INLINE idComplex &idComplex::operator+=( const float a ) { 225 r += a; 226 return *this; 227 } 228 229 ID_INLINE idComplex &idComplex::operator-=( const float a ) { 230 r -= a; 231 return *this; 232 } 233 234 ID_INLINE idComplex operator*( const float a, const idComplex &b ) { 235 return idComplex( a * b.r, a * b.i ); 236 } 237 238 ID_INLINE idComplex operator/( const float a, const idComplex &b ) { 239 float s, t; 240 if ( idMath::Fabs( b.r ) >= idMath::Fabs( b.i ) ) { 241 s = b.i / b.r; 242 t = a / ( b.r + s * b.i ); 243 return idComplex( t, - s * t ); 244 } else { 245 s = b.r / b.i; 246 t = a / ( s * b.r + b.i ); 247 return idComplex( s * t, - t ); 248 } 249 } 250 251 ID_INLINE idComplex operator+( const float a, const idComplex &b ) { 252 return idComplex( a + b.r, b.i ); 253 } 254 255 ID_INLINE idComplex operator-( const float a, const idComplex &b ) { 256 return idComplex( a - b.r, -b.i ); 257 } 258 259 ID_INLINE idComplex idComplex::Reciprocal() const { 260 float s, t; 261 if ( idMath::Fabs( r ) >= idMath::Fabs( i ) ) { 262 s = i / r; 263 t = 1.0f / ( r + s * i ); 264 return idComplex( t, - s * t ); 265 } else { 266 s = r / i; 267 t = 1.0f / ( s * r + i ); 268 return idComplex( s * t, - t ); 269 } 270 } 271 272 ID_INLINE idComplex idComplex::Sqrt() const { 273 float x, y, w; 274 275 if ( r == 0.0f && i == 0.0f ) { 276 return idComplex( 0.0f, 0.0f ); 277 } 278 x = idMath::Fabs( r ); 279 y = idMath::Fabs( i ); 280 if ( x >= y ) { 281 w = y / x; 282 w = idMath::Sqrt( x ) * idMath::Sqrt( 0.5f * ( 1.0f + idMath::Sqrt( 1.0f + w * w ) ) ); 283 } else { 284 w = x / y; 285 w = idMath::Sqrt( y ) * idMath::Sqrt( 0.5f * ( w + idMath::Sqrt( 1.0f + w * w ) ) ); 286 } 287 if ( w == 0.0f ) { 288 return idComplex( 0.0f, 0.0f ); 289 } 290 if ( r >= 0.0f ) { 291 return idComplex( w, 0.5f * i / w ); 292 } else { 293 return idComplex( 0.5f * y / w, ( i >= 0.0f ) ? w : -w ); 294 } 295 } 296 297 ID_INLINE float idComplex::Abs() const { 298 float x, y, t; 299 x = idMath::Fabs( r ); 300 y = idMath::Fabs( i ); 301 if ( x == 0.0f ) { 302 return y; 303 } else if ( y == 0.0f ) { 304 return x; 305 } else if ( x > y ) { 306 t = y / x; 307 return x * idMath::Sqrt( 1.0f + t * t ); 308 } else { 309 t = x / y; 310 return y * idMath::Sqrt( 1.0f + t * t ); 311 } 312 } 313 314 ID_INLINE bool idComplex::Compare( const idComplex &a ) const { 315 return ( ( r == a.r ) && ( i == a.i ) ); 316 } 317 318 ID_INLINE bool idComplex::Compare( const idComplex &a, const float epsilon ) const { 319 if ( idMath::Fabs( r - a.r ) > epsilon ) { 320 return false; 321 } 322 if ( idMath::Fabs( i - a.i ) > epsilon ) { 323 return false; 324 } 325 return true; 326 } 327 328 ID_INLINE bool idComplex::operator==( const idComplex &a ) const { 329 return Compare( a ); 330 } 331 332 ID_INLINE bool idComplex::operator!=( const idComplex &a ) const { 333 return !Compare( a ); 334 } 335 336 ID_INLINE int idComplex::GetDimension() const { 337 return 2; 338 } 339 340 ID_INLINE const float *idComplex::ToFloatPtr() const { 341 return &r; 342 } 343 344 ID_INLINE float *idComplex::ToFloatPtr() { 345 return &r; 346 } 347 348 #endif /* !__MATH_COMPLEX_H__ */