conjugate.h

Go to the documentation of this file.
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_

Generated on Wed Dec 30 11:04:32 2009 for SimTKcore by  doxygen 1.6.1