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