Simbody
|
00001 #ifndef SimTK_SIMMATRIX_CONJUGATE_H_ 00002 #define SimTK_SIMMATRIX_CONJUGATE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simmatrix(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2005-7 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00068 #include <complex> 00069 #include <iostream> 00070 #include <limits> 00071 00072 using std::complex; 00073 00074 00075 // These mixed-precision real/complex operators should not be needed 00076 // and may have to be removed on some systems. However neither 00077 // gcc 3.4.4 nor VC++ 7 provide them. 00078 // Define the symbol below if these conflict with standard library operators. 00079 00080 #ifndef SimTK_MIXED_PRECISION_REAL_COMPLEX_ALREADY_DEFINED 00081 namespace SimTK { 00082 // complex<float> with int, double, long double 00083 inline complex<float> operator*(const complex<float>& c,int r) {return c*(float)r;} 00084 inline complex<float> operator*(int r,const complex<float>& c) {return (float)r*c;} 00085 inline complex<double> operator*(const complex<float>& c,const double& r) {return complex<double>(c)*r;} 00086 inline complex<double> operator*(const double& r,const complex<float>& c) {return r*complex<double>(c);} 00087 inline complex<long double> operator*(const complex<float>& c,const long double& r) {return complex<long double>(c)*r;} 00088 inline complex<long double> operator*(const long double& r,const complex<float>& c) {return r*complex<long double>(c);} 00089 00090 inline complex<float> operator/(const complex<float>& c,int r) {return c/(float)r;} 00091 inline complex<float> operator/(int r,const complex<float>& c) {return (float)r/c;} 00092 inline complex<double> operator/(const complex<float>& c,const double& r) {return complex<double>(c)/r;} 00093 inline complex<double> operator/(const double& r,const complex<float>& c) {return r/complex<double>(c);} 00094 inline complex<long double> operator/(const complex<float>& c,const long double& r) {return complex<long double>(c)/r;} 00095 inline complex<long double> operator/(const long double& r,const complex<float>& c) {return r/complex<long double>(c);} 00096 00097 inline complex<float> operator+(const complex<float>& c,int r) {return c+(float)r;} 00098 inline complex<float> operator+(int r,const complex<float>& c) {return (float)r+c;} 00099 inline complex<double> operator+(const complex<float>& c,const double& r) {return complex<double>(c)+r;} 00100 inline complex<double> operator+(const double& r,const complex<float>& c) {return r+complex<double>(c);} 00101 inline complex<long double> operator+(const complex<float>& c,const long double& r) {return complex<long double>(c)+r;} 00102 inline complex<long double> operator+(const long double& r,const complex<float>& c) {return r+complex<long double>(c);} 00103 00104 inline complex<float> operator-(const complex<float>& c,int r) {return c-(float)r;} 00105 inline complex<float> operator-(int r,const complex<float>& c) {return (float)r-c;} 00106 inline complex<double> operator-(const complex<float>& c,const double& r) {return complex<double>(c)-r;} 00107 inline complex<double> operator-(const double& r,const complex<float>& c) {return r-complex<double>(c);} 00108 inline complex<long double> operator-(const complex<float>& c,const long double& r) {return complex<long double>(c)-r;} 00109 inline complex<long double> operator-(const long double& r,const complex<float>& c) {return r-complex<long double>(c);} 00110 00111 // complex<double> with int, float, long double 00112 inline complex<double> operator*(const complex<double>& c,int r) {return c*(double)r;} 00113 inline complex<double> operator*(int r,const complex<double>& c) {return (double)r*c;} 00114 inline complex<double> operator*(const complex<double>& c,const float& r) {return c*(double)r;} 00115 inline complex<double> operator*(const float& r,const complex<double>& c) {return (double)r*c;} 00116 inline complex<long double> operator*(const complex<double>& c,const long double& r){return complex<long double>(c)*r;} 00117 inline complex<long double> operator*(const long double& r,const complex<double>& c){return r*complex<long double>(c);} 00118 00119 inline complex<double> operator/(const complex<double>& c,int r) {return c/(double)r;} 00120 inline complex<double> operator/(int r,const complex<double>& c) {return (double)r/c;} 00121 inline complex<double> operator/(const complex<double>& c,const float& r) {return c/(double)r;} 00122 inline complex<double> operator/(const float& r,const complex<double>& c) {return (double)r/c;} 00123 inline complex<long double> operator/(const complex<double>& c,const long double& r){return complex<long double>(c)/r;} 00124 inline complex<long double> operator/(const long double& r,const complex<double>& c){return r/complex<long double>(c);} 00125 00126 inline complex<double> operator+(const complex<double>& c,int r) {return c+(double)r;} 00127 inline complex<double> operator+(int r,const complex<double>& c) {return (double)r+c;} 00128 inline complex<double> operator+(const complex<double>& c,const float& r) {return c+(double)r;} 00129 inline complex<double> operator+(const float& r,const complex<double>& c) {return (double)r+c;} 00130 inline complex<long double> operator+(const complex<double>& c,const long double& r){return complex<long double>(c)+r;} 00131 inline complex<long double> operator+(const long double& r,const complex<double>& c){return r+complex<long double>(c);} 00132 00133 inline complex<double> operator-(const complex<double>& c,int r) {return c-(double)r;} 00134 inline complex<double> operator-(int r,const complex<double>& c) {return (double)r-c;} 00135 inline complex<double> operator-(const complex<double>& c,const float& r) {return c-(double)r;} 00136 inline complex<double> operator-(const float& r,const complex<double>& c) {return (double)r-c;} 00137 inline complex<long double> operator-(const complex<double>& c,const long double& r){return complex<long double>(c)-r;} 00138 inline complex<long double> operator-(const long double& r,const complex<double>& c){return r-complex<long double>(c);} 00139 00140 // complex<long double> with int, float, double 00141 inline complex<long double> operator*(const complex<long double>& c,int r) {return c*(long double)r;} 00142 inline complex<long double> operator*(int r,const complex<long double>& c) {return (long double)r*c;} 00143 inline complex<long double> operator*(const complex<long double>& c,const float& r) {return c*(long double)r;} 00144 inline complex<long double> operator*(const float& r,const complex<long double>& c) {return (long double)r*c;} 00145 inline complex<long double> operator*(const complex<long double>& c,const double& r){return c*(long double)r;} 00146 inline complex<long double> operator*(const double& r,const complex<long double>& c){return (long double)r*c;} 00147 00148 inline complex<long double> operator/(const complex<long double>& c,int r) {return c/(long double)r;} 00149 inline complex<long double> operator/(int r,const complex<long double>& c) {return (long double)r/c;} 00150 inline complex<long double> operator/(const complex<long double>& c,const float& r) {return c/(long double)r;} 00151 inline complex<long double> operator/(const float& r,const complex<long double>& c) {return (long double)r/c;} 00152 inline complex<long double> operator/(const complex<long double>& c,const double& r){return c/(long double)r;} 00153 inline complex<long double> operator/(const double& r,const complex<long double>& c){return (long double)r/c;} 00154 00155 inline complex<long double> operator+(const complex<long double>& c,int r) {return c+(long double)r;} 00156 inline complex<long double> operator+(int r,const complex<long double>& c) {return (long double)r+c;} 00157 inline complex<long double> operator+(const complex<long double>& c,const float& r) {return c+(long double)r;} 00158 inline complex<long double> operator+(const float& r,const complex<long double>& c) {return (long double)r+c;} 00159 inline complex<long double> operator+(const complex<long double>& c,const double& r){return c+(long double)r;} 00160 inline complex<long double> operator+(const double& r,const complex<long double>& c){return (long double)r+c;} 00161 00162 inline complex<long double> operator-(const complex<long double>& c,int r) {return c-(long double)r;} 00163 inline complex<long double> operator-(int r,const complex<long double>& c) {return (long double)r-c;} 00164 inline complex<long double> operator-(const complex<long double>& c,const float& r) {return c-(long double)r;} 00165 inline complex<long double> operator-(const float& r,const complex<long double>& c) {return (long double)r-c;} 00166 inline complex<long double> operator-(const complex<long double>& c,const double& r){return c-(long double)r;} 00167 inline complex<long double> operator-(const double& r,const complex<long double>& c){return (long double)r-c;} 00168 } // namespace SimTK 00169 #endif 00170 00171 namespace SimTK { 00172 00173 template <class R> class conjugate; // Only defined for float, double, long double 00174 template <> class conjugate<float>; 00175 template <> class conjugate<double>; 00176 template <> class conjugate<long double>; 00177 00178 // This is an adaptor for number types which negates the apparent values. A 00179 // negator<N> has exactly the same internal representation as a number 00180 // type N, but it is to be interpreted has having the negative of the value 00181 // it would have if interpreted as an N. This permits negation to be done 00182 // by reinterpretation rather than computation. A full set of arithmetic operators 00183 // are provided involving negator<N>'s and N's. Sometimes we can save an op or 00184 // two this way. For example negator<N>*negator<N> can be performed as an N*N 00185 // since the negations cancel, and we saved two floating point negations. 00186 template <class N> class negator; // Only defined for numbers 00187 00188 /* 00189 * This class is specialized for all 9 combinations of built-in real types 00190 * and contains a typedef for the appropriate "widened" real, complex, or 00191 * conjugate type for use when R1 & R2 appear in an operation together. 00192 */ 00193 template <class R1, class R2> struct Wider {/* Only defined for built-ins. */}; 00194 template <> struct Wider<float,float> { 00195 typedef float WReal; 00196 typedef complex<float> WCplx; 00197 typedef conjugate<float> WConj; 00198 }; 00199 template <> struct Wider<float,double> { 00200 typedef double WReal; 00201 typedef complex<double> WCplx; 00202 typedef conjugate<double> WConj; 00203 }; 00204 template <> struct Wider<double,float> { 00205 typedef double WReal; 00206 typedef complex<double> WCplx; 00207 typedef conjugate<double> WConj; 00208 }; 00209 template <> struct Wider<double,double> { 00210 typedef double WReal; 00211 typedef complex<double> WCplx; 00212 typedef conjugate<double> WConj; 00213 }; 00214 template <> struct Wider<float,long double> { 00215 typedef long double WReal; 00216 typedef complex<long double> WCplx; 00217 typedef conjugate<long double> WConj; 00218 }; 00219 template <> struct Wider<double,long double> { 00220 typedef long double WReal; 00221 typedef complex<long double> WCplx; 00222 typedef conjugate<long double> WConj; 00223 }; 00224 template <> struct Wider<long double,float> { 00225 typedef long double WReal; 00226 typedef complex<long double> WCplx; 00227 typedef conjugate<long double> WConj; 00228 }; 00229 template <> struct Wider<long double,double> { 00230 typedef long double WReal; 00231 typedef complex<long double> WCplx; 00232 typedef conjugate<long double> WConj; 00233 }; 00234 template <> struct Wider<long double,long double> { 00235 typedef long double WReal; 00236 typedef complex<long double> WCplx; 00237 typedef conjugate<long double> WConj; 00238 }; 00239 00240 00257 template <class R> class conjugate {/*Only defined for float, double, long double*/}; 00258 00260 // Specialization for conjugate<float> // 00262 00263 template <> class conjugate<float> { 00264 public: 00265 conjugate() { 00266 #ifndef NDEBUG 00267 re = negIm = std::numeric_limits<float>::quiet_NaN(); 00268 #endif 00269 } 00270 // default copy constructor, copy assignment, destructor 00271 00273 conjugate(const float& real, const float& imag) { re = real; negIm = imag; } 00274 conjugate(const float& real, int i) { re = real; negIm = float(i); } 00275 conjugate(int r, const float& imag) { re = float(r); negIm = imag; } 00276 conjugate(int r, int i) { re = float(r); negIm = float(i); } 00277 00279 conjugate(const float& real) { re = real; negIm = 0.f; } 00280 conjugate(int r) { re = float(r); negIm = 0.f; } 00281 00282 // No implicit conversions from double or long double because precision 00283 // will be lost. Some definitions must be deferred until conjugate<double> 00284 // and conjugate<long double> are defined below. 00285 inline explicit conjugate(const conjugate<double>& cd); 00286 inline explicit conjugate(const conjugate<long double>& cl); 00287 00288 explicit conjugate(const double& rd) 00289 { re = float(rd); negIm = 0.f; } 00290 explicit conjugate(const long double& rl) 00291 { re = float(rl); negIm = 0.f; } 00292 00293 // Conversions from complex are always explicit. Note that the value 00294 // represented by the conjugate must be identical to that represented by 00295 // the complex, which means we must negate the imaginary part. 00296 explicit conjugate(const complex<float>& x) 00297 { re = x.real(); negIm = -x.imag(); } 00298 explicit conjugate(const complex<double>& x) 00299 { re = float(x.real()); negIm = float(-x.imag()); } 00300 explicit conjugate(const complex<long double>& x) 00301 { re = float(x.real()); negIm = float(-x.imag()); } 00302 00305 operator complex<float>() const 00306 { return complex<float>(re,-negIm); } 00307 00308 // Can't defer here by casting to negator<conjugate> -- this must act 00309 // like a built-in. But ... we can use this as a chance to convert 00310 // to complex and save one negation. 00311 complex<float> operator-() const { return complex<float>(-re,negIm); } 00312 00313 // Useless. 00314 const conjugate& operator+() const { return *this; } 00315 00316 // Computed assignment operators. We don't depend on implicit conversions 00317 // from reals to conjugates here because we can save a few flops by handling 00318 // the reals explicitly. Note that we only provide operators for implicitly 00319 // convertible precisions, though, which in this case means only floats. 00320 conjugate& operator=(const float& r) 00321 { re = r; negIm = 0.f; return *this; } 00322 conjugate& operator+=(const float& r) 00323 { re += r; return *this; } 00324 conjugate& operator-=(const float& r) 00325 { re -= r; return *this; } 00326 conjugate& operator*=(const float& r) 00327 { re *= r; negIm *= r; return *this; } 00328 conjugate& operator/=(const float& r) 00329 { re /= r; negIm /= r; return *this; } 00330 00331 conjugate& operator+=(const conjugate<float>& c) 00332 { re += c.re; negIm += c.negIm; return *this; } 00333 conjugate& operator-=(const conjugate<float>& c) 00334 { re -= c.re; negIm -= c.negIm; return *this; } 00335 00336 conjugate& operator=(const complex<float>& c) 00337 { re = c.real(); negIm = -c.imag(); return *this; } 00338 conjugate& operator+=(const complex<float>& c) 00339 { re += c.real(); negIm -= c.imag(); return *this; } 00340 conjugate& operator-=(const complex<float>& c) 00341 { re -= c.real(); negIm += c.imag(); return *this; } 00342 00343 // It is pleasant to note that we can self-multiply by either a complex or 00344 // a conjugate (leaving a conjugate result) in six flops which is the same 00345 // cost as an ordinary complex multiply: 00346 // cplx=cplx*cplx: (a+bi)(r+si) = (ar-bs)+(as+br)i 00347 // conj=conj*conj: (a-bi)(r-si) = (ar-bs)-(as+br)i 00348 // conj=conj*cplx: (a-bi)(r+si) = (ar+bs)-(br-as)i 00349 conjugate& operator*=(const conjugate<float>& c) { 00350 const float r=(re*c.re - negIm*c.negIm); 00351 negIm=(re*c.negIm + negIm*c.re); re=r; return *this; 00352 } 00353 conjugate& operator*=(const complex<float>& t) { 00354 const float r=(re*t.real() + negIm*t.imag()); 00355 negIm=(negIm*t.real() - re*t.imag()); re=r; return *this; 00356 } 00357 00358 // Complex divide is messy and slow anyway so we'll convert to complex and back here, 00359 // making use of the fact that for complex c and d, c/d=conj(conj(c)/conj(d)). 00360 conjugate& operator/=(const conjugate<float>& d) { 00361 const complex<float> t = conj()/d.conj(); 00362 re = t.real(); negIm = t.imag(); // conjugating! 00363 return *this; 00364 } 00365 conjugate& operator/=(const complex<float>& d) { 00366 const complex<float> t = conj()/std::conj(d); 00367 re = t.real(); negIm = t.imag(); // conjugating! 00368 return *this; 00369 } 00370 00371 const float& real() const { return re; } 00372 float& real() { return re; } 00373 00374 const negator<float>& imag() const { return reinterpret_cast<const negator<float>&>(negIm); } 00375 negator<float>& imag() { return reinterpret_cast<negator<float>&>(negIm); } 00376 00377 const complex<float>& conj() const { return reinterpret_cast<const complex<float>&>(*this); } 00378 complex<float>& conj() { return reinterpret_cast<complex<float>&>(*this); } 00379 00380 // Special conjugate methods of use primarily in operator implementations. 00381 const float& negImag() const { return negIm; } 00382 float& negImag() { return negIm; } 00383 bool isReal() const { return negIm==0.f; } 00384 00385 private: 00386 float re; // The value represented here is re - negIm*i. 00387 float negIm; 00388 }; 00389 00390 00391 00392 00394 // Specialization for conjugate<double> // 00396 00397 template <> class conjugate<double> { 00398 public: 00399 conjugate() { 00400 #ifndef NDEBUG 00401 re = negIm = std::numeric_limits<double>::quiet_NaN(); 00402 #endif 00403 } 00404 // default copy constructor, copy assignment, destructor 00405 00407 conjugate(const double& real, const double& imag) { re = real; negIm = imag; } 00408 conjugate(const double& real, int i) { re = real; negIm = double(i); } 00409 conjugate(int r, const double& imag) { re = double(r); negIm = imag; } 00410 conjugate(int r, int i) { re = double(r); negIm = double(i); } 00411 00413 conjugate(const double& real) { re = real; negIm = 0.; } 00414 conjugate(int r) { re = double(r); negIm = 0.; } 00415 00416 // Implicit conversions from float are allowed since 00417 // there is no loss in going to double, but long double 00418 // requires explicit conversions. 00419 conjugate(const conjugate<float>& cf) 00420 { re = double(cf.real()); negIm = double(cf.negImag()); } 00421 conjugate(const float& rf) 00422 { re = double(rf); negIm = 0.; } 00423 00424 // Definition must be deferred until conjugate<long double> is defined below. 00425 inline explicit conjugate(const conjugate<long double>& cl); 00426 explicit conjugate(const long double& rl) 00427 { re = double(rl); negIm = 0.; } 00428 00429 // Conversions from complex are always explicit. Note that the value 00430 // represented by the conjugate must be identical to that represented by 00431 // the complex, which means we must negate the imaginary part. 00432 explicit conjugate(const complex<float>& x) 00433 { re = double(x.real()); negIm = double(-x.imag()); } 00434 explicit conjugate(const complex<double>& x) 00435 { re = x.real(); negIm = -x.imag(); } 00436 explicit conjugate(const complex<long double>& x) 00437 { re = double(x.real()); negIm = double(-x.imag()); } 00438 00441 operator complex<double>() const 00442 { return complex<double>(re,-negIm); } 00443 00444 // Can't defer here by casting to negator<conjugate> -- this must act 00445 // like a built-in. But ... we can use this as a chance to convert 00446 // to complex and save one negation. 00447 complex<double> operator-() const { return complex<double>(-re,negIm); } 00448 00449 // Useless. 00450 const conjugate& operator+() const { return *this; } 00451 00452 // Computed assignment operators. We don't depend on implicit conversions 00453 // from reals to conjugates here because we can save a few flops by handling 00454 // the reals explicitly. Note that we only provide operators for implicitly 00455 // convertible precisions, though, which in this case means floats and doubles. 00456 conjugate& operator=(const double& r) 00457 { re = r; negIm = 0.; return *this; } 00458 conjugate& operator+=(const double& r) 00459 { re += r; return *this; } 00460 conjugate& operator-=(const double& r) 00461 { re -= r; return *this; } 00462 conjugate& operator*=(const double& r) 00463 { re *= r; negIm *= r; return *this; } 00464 conjugate& operator/=(const double& r) 00465 { re /= r; negIm /= r; return *this; } 00466 00467 conjugate& operator=(const float& r) 00468 { re = r; negIm = 0.; return *this; } 00469 conjugate& operator+=(const float& r) 00470 { re += r; return *this; } 00471 conjugate& operator-=(const float& r) 00472 { re -= r; return *this; } 00473 conjugate& operator*=(const float& r) 00474 { re *= r; negIm *= r; return *this; } 00475 conjugate& operator/=(const float& r) 00476 { re /= r; negIm /= r; return *this; } 00477 00478 // Disambiguate int to be a double. 00479 conjugate& operator =(int i) {*this =(double)i; return *this;} 00480 conjugate& operator+=(int i) {*this+=(double)i; return *this;} 00481 conjugate& operator-=(int i) {*this-=(double)i; return *this;} 00482 conjugate& operator*=(int i) {*this*=(double)i; return *this;} 00483 conjugate& operator/=(int i) {*this/=(double)i; return *this;} 00484 00485 conjugate& operator+=(const conjugate<double>& c) 00486 { re += c.re; negIm += c.negIm; return *this; } 00487 conjugate& operator-=(const conjugate<double>& c) 00488 { re -= c.re; negIm -= c.negIm; return *this; } 00489 00490 conjugate& operator+=(const conjugate<float>& c) 00491 { re += c.real(); negIm += c.negImag(); return *this; } 00492 conjugate& operator-=(const conjugate<float>& c) 00493 { re -= c.real(); negIm -= c.negImag(); return *this; } 00494 00495 conjugate& operator=(const complex<double>& c) 00496 { re = c.real(); negIm = -c.imag(); return *this; } 00497 conjugate& operator+=(const complex<double>& c) 00498 { re += c.real(); negIm -= c.imag(); return *this; } 00499 conjugate& operator-=(const complex<double>& c) 00500 { re -= c.real(); negIm += c.imag(); return *this; } 00501 00502 conjugate& operator=(const complex<float>& c) 00503 { re = c.real(); negIm = -c.imag(); return *this; } 00504 conjugate& operator+=(const complex<float>& c) 00505 { re += c.real(); negIm -= c.imag(); return *this; } 00506 conjugate& operator-=(const complex<float>& c) 00507 { re -= c.real(); negIm += c.imag(); return *this; } 00508 00509 // It is pleasant to note that we can self-multiply by either a complex or 00510 // a conjugate (leaving a conjugate result) in six flops which is the same 00511 // cost as an ordinary complex multiply: 00512 // cplx=cplx*cplx: (a+bi)(r+si) = (ar-bs)+(as+br)i 00513 // conj=conj*conj: (a-bi)(r-si) = (ar-bs)-(as+br)i 00514 // conj=conj*cplx: (a-bi)(r+si) = (ar+bs)-(br-as)i 00515 conjugate& operator*=(const conjugate<double>& c) { 00516 const double r=(re*c.re - negIm*c.negIm); 00517 negIm=(re*c.negIm + negIm*c.re); re=r; return *this; 00518 } 00519 conjugate& operator*=(const complex<double>& t) { 00520 const double r=(re*t.real() + negIm*t.imag()); 00521 negIm=(negIm*t.real() - re*t.imag()); re=r; return *this; 00522 } 00523 00524 conjugate& operator*=(const conjugate<float>& c) { return operator*=(conjugate<double>(c)); } 00525 conjugate& operator*=(const complex<float>& c) { return operator*=(complex<double>(c)); } 00526 00527 // Complex divide is messy and slow anyway so we'll convert to complex and back here, 00528 // making use of the fact that for complex c and d, c/d=conj(conj(c)/conj(d)). 00529 conjugate& operator/=(const conjugate<double>& d) { 00530 const complex<double> t = conj()/d.conj(); 00531 re = t.real(); negIm = t.imag(); // conjugating! 00532 return *this; 00533 } 00534 conjugate& operator/=(const complex<double>& d) { 00535 const complex<double> t = conj()/std::conj(d); 00536 re = t.real(); negIm = t.imag(); // conjugating! 00537 return *this; 00538 } 00539 00540 conjugate& operator/=(const conjugate<float>& c) { return operator/=(conjugate<double>(c)); } 00541 conjugate& operator/=(const complex<float>& c) { return operator/=(complex<double>(c)); } 00542 00543 const double& real() const { return re; } 00544 double& real() { return re; } 00545 00546 const negator<double>& imag() const { return reinterpret_cast<const negator<double>&>(negIm); } 00547 negator<double>& imag() { return reinterpret_cast<negator<double>&>(negIm); } 00548 00549 const complex<double>& conj() const { return reinterpret_cast<const complex<double>&>(*this); } 00550 complex<double>& conj() { return reinterpret_cast<complex<double>&>(*this); } 00551 00552 // Special conjugate methods of use primarily in operator implementations. 00553 const double& negImag() const { return negIm; } 00554 double& negImag() { return negIm; } 00555 bool isReal() const { return negIm==0.; } 00556 00557 private: 00558 double re; // The value represented here is re - negIm*i. 00559 double negIm; 00560 }; 00561 00562 00563 00565 // Specialization for conjugate<long double> // 00567 00568 template <> class conjugate<long double> { 00569 public: 00570 conjugate() { 00571 #ifndef NDEBUG 00572 re = negIm = std::numeric_limits<long double>::quiet_NaN(); 00573 #endif 00574 } 00575 // default copy constructor, copy assignment, destructor 00576 00578 conjugate(const long double& real, const long double& imag) { re = real; negIm = imag; } 00579 conjugate(const long double& real, int i) { re = real; negIm = (long double)i; } 00580 conjugate(int r, const long double& imag) { re = (long double)r; negIm = imag; } 00581 conjugate(int r, int i) { re = (long double)r; negIm = (long double)i; } 00582 00584 conjugate(const long double& real) { re = real; negIm = 0.L; } 00585 conjugate(int r) { re = (long double)r; negIm = 0.L; } 00586 00587 // Implicit conversions from float and double are allowed since 00588 // there is no loss in going to long double. 00589 conjugate(const conjugate<float>& cf) 00590 { re = (long double)cf.real(); negIm = (long double)cf.negImag(); } 00591 conjugate(const conjugate<double>& cd) 00592 { re = (long double)cd.real(); negIm = (long double)cd.negImag(); } 00593 00594 conjugate(const float& rf) 00595 { re = (long double)rf; negIm = 0.L; } 00596 conjugate(const double& rd) 00597 { re = (long double)rd; negIm = 0.L; } 00598 00599 00600 // Conversions from complex are always explicit. Note that the value 00601 // represented by the conjugate must be identical to that represented by 00602 // the complex, which means we must negate the imaginary part. 00603 explicit conjugate(const complex<float>& x) 00604 { re = (long double)x.real(); negIm = (long double)(-x.imag()); } 00605 explicit conjugate(const complex<double>& x) 00606 { re = (long double)x.real(); negIm = (long double)(-x.imag()); } 00607 explicit conjugate(const complex<long double>& x) 00608 { re = x.real(); negIm = -x.imag(); } 00609 00612 operator complex<long double>() const 00613 { return complex<long double>(re,-negIm); } 00614 00615 // Can't defer here by casting to negator<conjugate> -- this must act 00616 // like a built-in. But ... we can use this as a chance to convert 00617 // to complex and save one negation. 00618 complex<long double> operator-() const 00619 { return complex<long double>(-re,negIm); } 00620 00621 // Useless. 00622 const conjugate& operator+() const { return *this; } 00623 00624 // Computed assignment operators. We don't depend on implicit conversions 00625 // from reals to conjugates here because we can save a few flops by handling 00626 // the reals explicitly. Note that we only provide operators for implicitly 00627 // convertible precisions, though, which in this case means any floating 00628 // point precision. 00629 conjugate& operator=(const long double& r) 00630 { re = r; negIm = 0.L; return *this; } 00631 conjugate& operator+=(const long double& r) 00632 { re += r; return *this; } 00633 conjugate& operator-=(const long double& r) 00634 { re -= r; return *this; } 00635 conjugate& operator*=(const long double& r) 00636 { re *= r; negIm *= r; return *this; } 00637 conjugate& operator/=(const long double& r) 00638 { re /= r; negIm /= r; return *this; } 00639 00640 conjugate& operator=(const double& r) 00641 { re = r; negIm = 0.L; return *this; } 00642 conjugate& operator+=(const double& r) 00643 { re += r; return *this; } 00644 conjugate& operator-=(const double& r) 00645 { re -= r; return *this; } 00646 conjugate& operator*=(const double& r) 00647 { re *= r; negIm *= r; return *this; } 00648 conjugate& operator/=(const double& r) 00649 { re /= r; negIm /= r; return *this; } 00650 00651 conjugate& operator=(const float& r) 00652 { re = r; negIm = 0.L; return *this; } 00653 conjugate& operator+=(const float& r) 00654 { re += r; return *this; } 00655 conjugate& operator-=(const float& r) 00656 { re -= r; return *this; } 00657 conjugate& operator*=(const float& r) 00658 { re *= r; negIm *= r; return *this; } 00659 conjugate& operator/=(const float& r) 00660 { re /= r; negIm /= r; return *this; } 00661 00662 // Disambiguate int to be a long double. 00663 conjugate& operator =(int i) {*this =(long double)i; return *this;} 00664 conjugate& operator+=(int i) {*this+=(long double)i; return *this;} 00665 conjugate& operator-=(int i) {*this-=(long double)i; return *this;} 00666 conjugate& operator*=(int i) {*this*=(long double)i; return *this;} 00667 conjugate& operator/=(int i) {*this/=(long double)i; return *this;} 00668 00669 conjugate& operator+=(const conjugate<long double>& c) 00670 { re += c.re; negIm += c.negIm; return *this; } 00671 conjugate& operator-=(const conjugate<long double>& c) 00672 { re -= c.re; negIm -= c.negIm; return *this; } 00673 00674 conjugate& operator+=(const conjugate<double>& c) 00675 { re += c.real(); negIm += c.negImag(); return *this; } 00676 conjugate& operator-=(const conjugate<double>& c) 00677 { re -= c.real(); negIm -= c.negImag(); return *this; } 00678 00679 conjugate& operator+=(const conjugate<float>& c) 00680 { re += c.real(); negIm += c.negImag(); return *this; } 00681 conjugate& operator-=(const conjugate<float>& c) 00682 { re -= c.real(); negIm -= c.negImag(); return *this; } 00683 00684 conjugate& operator=(const complex<long double>& c) 00685 { re = c.real(); negIm = -c.imag(); return *this; } 00686 conjugate& operator+=(const complex<long double>& c) 00687 { re += c.real(); negIm -= c.imag(); return *this; } 00688 conjugate& operator-=(const complex<long double>& c) 00689 { re -= c.real(); negIm += c.imag(); return *this; } 00690 00691 conjugate& operator=(const complex<double>& c) 00692 { re = c.real(); negIm = -c.imag(); return *this; } 00693 conjugate& operator+=(const complex<double>& c) 00694 { re += c.real(); negIm -= c.imag(); return *this; } 00695 conjugate& operator-=(const complex<double>& c) 00696 { re -= c.real(); negIm += c.imag(); return *this; } 00697 00698 conjugate& operator=(const complex<float>& c) 00699 { re = c.real(); negIm = -c.imag(); return *this; } 00700 conjugate& operator+=(const complex<float>& c) 00701 { re += c.real(); negIm -= c.imag(); return *this; } 00702 conjugate& operator-=(const complex<float>& c) 00703 { re -= c.real(); negIm += c.imag(); return *this; } 00704 00705 // It is pleasant to note that we can self-multiply by either a complex or 00706 // a conjugate (leaving a conjugate result) in six flops which is the same 00707 // cost as an ordinary complex multiply: 00708 // cplx=cplx*cplx: (a+bi)(r+si) = (ar-bs)+(as+br)i 00709 // conj=conj*conj: (a-bi)(r-si) = (ar-bs)-(as+br)i 00710 // conj=conj*cplx: (a-bi)(r+si) = (ar+bs)-(br-as)i 00711 conjugate& operator*=(const conjugate<long double>& c) { 00712 const long double r=(re*c.re - negIm*c.negIm); 00713 negIm=(re*c.negIm + negIm*c.re); re=r; return *this; 00714 } 00715 conjugate& operator*=(const complex<long double>& t) { 00716 const long double r=(re*t.real() + negIm*t.imag()); 00717 negIm=(negIm*t.real() - re*t.imag()); re=r; return *this; 00718 } 00719 00720 conjugate& operator*=(const conjugate<double>& c) { return operator*=(conjugate<long double>(c)); } 00721 conjugate& operator*=(const complex<double>& c) { return operator*=(complex<long double>(c)); } 00722 conjugate& operator*=(const conjugate<float>& c) { return operator*=(conjugate<long double>(c)); } 00723 conjugate& operator*=(const complex<float>& c) { return operator*=(complex<long double>(c)); } 00724 00725 // Complex divide is messy and slow anyway so we'll convert to complex and back here, 00726 // making use of the fact that for complex c and d, c/d=conj(conj(c)/conj(d)). 00727 conjugate& operator/=(const conjugate<long double>& d) { 00728 const complex<long double> t = conj()/d.conj(); 00729 re = t.real(); negIm = t.imag(); // conjugating! 00730 return *this; 00731 } 00732 conjugate& operator/=(const complex<long double>& d) { 00733 const complex<long double> t = conj()/std::conj(d); 00734 re = t.real(); negIm = t.imag(); // conjugating! 00735 return *this; 00736 } 00737 00738 conjugate& operator/=(const conjugate<double>& c) { return operator/=(conjugate<long double>(c)); } 00739 conjugate& operator/=(const complex<double>& c) { return operator/=(complex<long double>(c)); } 00740 conjugate& operator/=(const conjugate<float>& c) { return operator/=(conjugate<long double>(c)); } 00741 conjugate& operator/=(const complex<float>& c) { return operator/=(complex<long double>(c)); } 00742 00743 const long double& real() const { return re; } 00744 long double& real() { return re; } 00745 00746 const negator<long double>& imag() const { return reinterpret_cast<const negator<long double>&>(negIm); } 00747 negator<long double>& imag() { return reinterpret_cast<negator<long double>&>(negIm); } 00748 00749 const complex<long double>& conj() const { return reinterpret_cast<const complex<long double>&>(*this); } 00750 complex<long double>& conj() { return reinterpret_cast<complex<long double>&>(*this); } 00751 00752 // Special conjugate methods of use primarily in operator implementations. 00753 const long double& negImag() const { return negIm; } 00754 long double& negImag() { return negIm; } 00755 bool isReal() const { return negIm==0.L; } 00756 00757 private: 00758 long double re; // The value represented here is re - negIm*i. 00759 long double negIm; 00760 }; 00761 00762 // These definitions had to be deferred until all the specializations have been declared. 00763 conjugate<float>::conjugate(const conjugate<double>& cd) { 00764 re = float(cd.real()); negIm = float(cd.negImag()); 00765 } 00766 conjugate<float>::conjugate(const conjugate<long double>& cl) { 00767 re = float(cl.real()); negIm = float(cl.negImag()); 00768 } 00769 conjugate<double>::conjugate(const conjugate<long double>& cl) { 00770 re = double(cl.real()); negIm = double(cl.negImag()); 00771 } 00772 00773 // Global functions real(),imag(), conj(), abs(), and norm() are overloaded here 00774 // for efficiency (e.g., abs(c)==abs(conj(c))). The others still work through 00775 // the implicit conversion from conjugate<T> to complex<T>, which costs 00776 // one negation. The non-overloaded functions defined for complex are 00777 // arg(), which returns a real, and a set of functions which return complex: 00778 // polar,cos,cosh,exp,log,log10,pow,sin,sinh,sqrt,tan,tanh. 00779 inline const float& real(const conjugate<float>& c) { return c.real(); } 00780 inline const negator<float>& imag(const conjugate<float>& c) { return c.imag(); } 00781 inline const complex<float>& conj(const conjugate<float>& c) { return c.conj(); } 00782 inline float abs (const conjugate<float>& c) { return std::abs(c.conj()); } 00783 inline float norm(const conjugate<float>& c) { return std::norm(c.conj()); } 00784 00785 inline const double& real(const conjugate<double>& c) { return c.real(); } 00786 inline const negator<double>& imag(const conjugate<double>& c) { return c.imag(); } 00787 inline const complex<double>& conj(const conjugate<double>& c) { return c.conj(); } 00788 inline double abs (const conjugate<double>& c) { return std::abs(c.conj()); } 00789 inline double norm(const conjugate<double>& c) { return std::norm(c.conj()); } 00790 00791 inline const long double& real(const conjugate<long double>& c) { return c.real(); } 00792 inline const negator<long double>& imag(const conjugate<long double>& c) { return c.imag(); } 00793 inline const complex<long double>& conj(const conjugate<long double>& c) { return c.conj(); } 00794 inline long double abs (const conjugate<long double>& c) { return std::abs(c.conj()); } 00795 inline long double norm(const conjugate<long double>& c) { return std::norm(c.conj()); } 00796 00797 00798 00799 00800 00801 00802 // Binary operators with conjugate as one of the operands, and the other any 00803 // numerical type (real, complex, conjugate) but NOT a negator type. Each operator 00804 // will silently work with operands of mixed precision, widening the result as 00805 // necessary. We try to return complex rather than conjugate whenever possible. 00806 00807 template <class R, class CHAR, class TRAITS> inline std::basic_istream<CHAR,TRAITS>& 00808 operator>>(std::basic_istream<CHAR,TRAITS>& is, conjugate<R>& c) { 00809 complex<R> z; is >> z; c=z; 00810 return is; 00811 } 00812 template <class R, class CHAR, class TRAITS> inline std::basic_ostream<CHAR,TRAITS>& 00813 operator<<(std::basic_ostream<CHAR,TRAITS>& os, const conjugate<R>& c) { 00814 return os << complex<R>(c); 00815 } 00816 00817 // Operators involving only conjugate and complex can be templatized reliably, as can 00818 // operators which do not mix precision. But we have to deal explicitly with mixes 00819 // of conjugate<R> and some other real type S, because the 'class S' template 00820 // argument can match anything and create ambiguities. 00821 00822 // conjugate<R> with float, double, long double. With 'float' we can be sure that R 00823 // is the right width for the return value. With 'long double' we are sure that 00824 // 'long double' is the return width. 'double' is trickier and we have to use the 00825 // Wider<R,...> helper class to give us the right return type. 00826 00827 // Commutative ops need be done only once: +, *, ==, and != is defined in terms of ==. 00828 00829 // conjugate = conjugate + real 00830 template <class R> inline conjugate<R> operator+(const conjugate<R>& a, const float& b) 00831 { return conjugate<R>(a) += b; } 00832 template <class R> inline conjugate<long double> operator+(const conjugate<R>& a, const long double& b) 00833 { return conjugate<long double>(a) += b; } 00834 template <class R> inline typename Wider<R,double>::WConj operator+(const conjugate<R>& a, const double& b) 00835 { return typename Wider<R,double>::WConj(a) += b; } 00836 00837 // conjugate = real + conjugate 00838 template <class R> inline conjugate<R> operator+(const float& a, const conjugate<R>& b) {return b+a;} 00839 template <class R> inline conjugate<long double> operator+(const long double& a, const conjugate<R>& b) {return b+a;} 00840 template <class R> inline typename Wider<R,double>::WConj operator+(const double& a, const conjugate<R>& b) {return b+a;} 00841 00842 // conjugate = conjugate * real 00843 template <class R> inline conjugate<R> operator*(const conjugate<R>& a, const float& b) 00844 { return conjugate<R>(a) *= b; } 00845 template <class R> inline conjugate<long double> operator*(const conjugate<R>& a, const long double& b) 00846 { return conjugate<long double>(a) *= b; } 00847 template <class R> inline typename Wider<R,double>::WConj operator*(const conjugate<R>& a, const double& b) 00848 { return typename Wider<R,double>::WConj(a) *= b; } 00849 00850 // conjugate = real * conjugate 00851 template <class R> inline conjugate<R> operator*(const float& a, const conjugate<R>& b) {return b*a;} 00852 template <class R> inline conjugate<long double> operator*(const long double& a, const conjugate<R>& b) {return b*a;} 00853 template <class R> inline typename Wider<R,double>::WConj operator*(const double& a, const conjugate<R>& b) {return b*a;} 00854 00855 // bool = conjugate==real 00856 template <class R> inline bool operator==(const conjugate<R>& a, const float& b) 00857 { return a.isReal() && a.real()==b; } 00858 template <class R> inline bool operator==(const conjugate<R>& a, const long double& b) 00859 { return a.isReal() && a.real()==b; } 00860 template <class R> inline bool operator==(const conjugate<R>& a, const double& b) 00861 { return a.isReal() && a.real()==b; } 00862 00863 // bool = real==conjugate, bool = conjugate!=real, bool = real!=conjugate 00864 template <class R> inline bool operator==(const float& a, const conjugate<R>& b) {return b==a;} 00865 template <class R> inline bool operator==(const long double& a, const conjugate<R>& b) {return b==a;} 00866 template <class R> inline bool operator==(const double& a, const conjugate<R>& b) {return b==a;} 00867 template <class R> inline bool operator!=(const conjugate<R>& a, const float& b) {return !(a==b);} 00868 template <class R> inline bool operator!=(const conjugate<R>& a, const long double& b) {return !(a==b);} 00869 template <class R> inline bool operator!=(const conjugate<R>& a, const double& b) {return !(a==b);} 00870 template <class R> inline bool operator!=(const float& a, const conjugate<R>& b) {return !(a==b);} 00871 template <class R> inline bool operator!=(const long double& a, const conjugate<R>& b) {return !(a==b);} 00872 template <class R> inline bool operator!=(const double& a, const conjugate<R>& b) {return !(a==b);} 00873 00874 // Non-commutative ops are a little messier. 00875 00876 // conjugate = conjugate - real 00877 template <class R> inline conjugate<R> operator-(const conjugate<R>& a, const float& b) 00878 { return conjugate<R>(a) -= b; } 00879 template <class R> inline conjugate<long double> operator-(const conjugate<R>& a, const long double& b) 00880 { return conjugate<long double>(a) -= b; } 00881 template <class R> inline typename Wider<R,double>::WConj operator-(const conjugate<R>& a, const double& b) 00882 { return typename Wider<R,double>::WConj(a) -= b; } 00883 00884 // complex = real - conjugate 00885 // This is nice because -conjugate.imag() is free. 00886 template <class R> inline complex<R> operator-(const float& a, const conjugate<R>& b) 00887 { return complex<R>(a-b.real(), -b.imag()); } 00888 template <class R> inline complex<long double> operator-(const long double& a, const conjugate<R>& b) 00889 { return complex<long double>(a-b.real(), -b.imag()); } 00890 template <class R> inline typename Wider<R,double>::WCplx operator-(const double& a, const conjugate<R>& b) 00891 { return typename Wider<R,double>::WCplx(a-b.real(), -b.imag()); } 00892 00893 // conjugate = conjugate / real 00894 template <class R> inline conjugate<R> operator/(const conjugate<R>& a, const float& b) 00895 { return conjugate<R>(a) /= b; } 00896 template <class R> inline conjugate<long double> operator/(const conjugate<R>& a, const long double& b) 00897 { return conjugate<long double>(a) /= b; } 00898 template <class R> inline typename Wider<R,double>::WConj operator/(const conjugate<R>& a, const double& b) 00899 { return typename Wider<R,double>::WConj(a) /= b; } 00900 00901 // complex = real / conjugate 00902 // Division by complex is tricky and slow anyway so we'll just convert to complex 00903 // at the cost of one negation. 00904 template <class R> inline complex<R> operator/(const float& a, const conjugate<R>& b) 00905 { return (R)a/complex<R>(b); } 00906 template <class R> inline complex<long double> operator/(const long double& a, const conjugate<R>& b) 00907 { return a/complex<long double>(b); } 00908 template <class R> inline typename Wider<R,double>::WCplx operator/(const double& a, const conjugate<R>& b) 00909 { return (typename Wider<R,double>::WReal)a/(typename Wider<R,double>::WCplx(b)); } 00910 00911 00912 // That's it for (conjugate, real) combinations. Now we need to do all the (conjugate, conjugate) and 00913 // (conjugate, complex) combinations which are safer to templatize fully. There are many more opportunities 00914 // to return complex rather than conjugate here. Keep in mind here that for a conjugate number c=a-bi, 00915 // a=c.real() and b=-c.imag() are available for free. conjugate provides negImag() to return b directly. 00916 // Below we'll capitalize components that should be accessed with negImag(). 00917 00918 // conjugate = conjugate + conjugate: (a-Bi)+(r-Si) = (a+r)-(B+S)i 00919 template <class R, class S> inline typename Wider<R,S>::WConj 00920 operator+(const conjugate<R>& a, const conjugate<S>& r) { 00921 return typename Wider<R,S>::WConj(a.real()+r.real(), 00922 a.negImag()+r.negImag()); 00923 } 00924 00925 // complex = conjugate + complex = complex + conjugate: (a-Bi)+(r+si) = (a+r)+(s-B)i 00926 template <class R, class S> inline typename Wider<R,S>::WCplx 00927 operator+(const conjugate<R>& a, const complex<S>& r) { 00928 return typename Wider<R,S>::WCplx(a.real()+r.real(), 00929 r.imag()-a.negImag()); 00930 } 00931 template <class R, class S> inline typename Wider<R,S>::WCplx 00932 operator+(const complex<R>& a, const conjugate<S>& r) { return r+a; } 00933 00934 // complex = conjugate - conjugate: (a-Bi)-(r-Si) = (a-r)+(S-B)i 00935 template <class R, class S> inline typename Wider<R,S>::WCplx 00936 operator-(const conjugate<R>& a, const conjugate<S>& r) { 00937 return typename Wider<R,S>::WCplx(a.real()-r.real(), 00938 r.negImag()-a.negImag()); 00939 } 00940 00941 // Neg<complex> = conjugate - complex: (a-Bi)-(r+si) = (a-r)+(-B-s)i = -[(r-a)+(B+s)i] 00942 template <class R, class S> inline negator<typename Wider<R,S>::WCplx> 00943 operator-(const conjugate<R>& a, const complex<S>& r) { 00944 return negator<typename Wider<R,S>::WCplx>::recast 00945 (typename Wider<R,S>::WCplx(r.real()-a.real(), 00946 a.negImag()+r.imag())); 00947 } 00948 00949 // complex = complex - conjugate: (a+bi)-(r-Si) = (a-r)+(b+S)i 00950 template <class R, class S> inline typename Wider<R,S>::WCplx 00951 operator-(const complex<R>& a, const conjugate<S>& r) { 00952 return typename Wider<R,S>::WCplx(a.real()-r.real(), 00953 a.imag()+r.negImag()); 00954 } 00955 00956 // We can multiply by either a complex or a conjugate (leaving a complex 00957 // or negated complex result) in six flops which is the same cost as an 00958 // ordinary complex multiply. 00959 // (cplx=cplx*cplx: (a+bi)(r+si) = (ar-bs)+(as+br)i) 00960 00961 // Neg<cplx>=conj*conj: (a-Bi)(r-Si) = -[(BS-ar)+(aS+Br)i] 00962 template <class R, class S> inline negator<typename Wider<R,S>::WCplx> 00963 operator*(const conjugate<R>& a, const conjugate<S>& r) { 00964 return negator<typename Wider<R,S>::WCplx>::recast 00965 (typename Wider<R,S>::WCplx(a.negImag()*r.negImag() - a.real()*r.real(), 00966 a.real()*r.negImag() + a.negImag()*r.real())); 00967 } 00968 00969 // cplx=conj*cplx: (a-Bi)(r+si) = (ar+Bs)+(as-Br)i 00970 template <class R, class S> inline typename Wider<R,S>::WCplx 00971 operator*(const conjugate<R>& a, const complex<S>& r) { 00972 return typename Wider<R,S>::WCplx(a.real()*r.real() + a.negImag()*r.imag(), 00973 a.real()*r.imag() - a.negImag()*r.real()); 00974 } 00975 00976 template <class R, class S> inline typename Wider<R,S>::WCplx 00977 operator*(const complex<R>& a, const conjugate<S>& r) 00978 { return r*a; } 00979 00980 // If there's a negator on the complex number, move it to the conjugate 00981 // one which will change to complex with just one flop; then this 00982 // is an ordinary complex mutiply. 00983 template <class R, class S> inline typename Wider<R,S>::WCplx 00984 operator*(const negator< complex<R> >& a, const conjugate<S>& r) 00985 { return (-a)*(-r); } // -a is free here 00986 template <class R, class S> inline typename Wider<R,S>::WCplx 00987 operator*(const conjugate<R>& a, const negator< complex<S> >& r) 00988 { return (-a)*(-r); } // -r is free here 00989 00990 // Division is tricky and there is little to gain by trying to exploit 00991 // the conjugate class, so we'll just convert to complex. (Remember that 00992 // conj() is free for Conjugates.) 00993 00994 template <class R, class S> inline typename Wider<R,S>::WCplx 00995 operator/(const conjugate<R>& a, const conjugate<S>& r) { 00996 return std::conj(a.conj()/r.conj()); 00997 } 00998 00999 template <class R, class S> inline typename Wider<R,S>::WCplx 01000 operator/(const conjugate<R>& a, const complex<S>& r) { 01001 return std::conj(a.conj()/std::conj(r)); 01002 } 01003 01004 template <class R, class S> inline typename Wider<R,S>::WCplx 01005 operator/(const complex<R>& a, const conjugate<S>& r) { 01006 return std::conj(std::conj(a)/r.conj()); 01007 } 01008 01009 01010 template <class R, class S> inline bool 01011 operator==(const conjugate<R>& a, const conjugate<S>& r) { 01012 return a.real() == r.real() && a.negImag() == r.negImag(); 01013 } 01014 01015 template <class R, class S> inline bool 01016 operator==(const conjugate<R>& a, const complex<S>& r) { 01017 return a.real() == r.real() && -a.negImag() == r.imag(); 01018 } 01019 01020 template <class R, class S> inline bool 01021 operator==(const complex<R>& a, const conjugate<S>& r) {return r==a;} 01022 01023 template <class R, class S> inline bool 01024 operator!=(const conjugate<R>& a, const conjugate<S>& r) {return !(a==r);} 01025 01026 template <class R, class S> inline bool 01027 operator!=(const conjugate<R>& a, const complex<S>& r) {return !(a==r);} 01028 01029 template <class R, class S> inline bool 01030 operator!=(const complex<R>& a, const conjugate<S>& r) {return !(a==r);} 01031 01032 01033 } // namespace SimTK 01034 01035 #endif //SimTK_SIMMATRIX_CONJUGATE_H_