Simbody  3.4 (development)
conjugate.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines