00001
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <math.h>
00015
00016 #include "CTB.hxx"
00017 #include "CTBnum.hxx"
00018 #include "CTBtraits.hxx"
00019 #include "CTBcomplex.hxx"
00020
00034
00036
00037 template <class T>
00038 CTBcomplex<T> CTBcomplex<T>::Sqrt() const
00039 {
00040 T f_re = 0.;
00041 T f_im = 0.;
00042
00043 if (IsReal()) {
00044 if (mf_re >= 0.) {
00045 f_re = sqrt(mf_re);
00046 } else {
00047 f_im = sqrt(-mf_re);
00048 }
00049
00050 } else {
00051 T f_abs = Abs();
00052 if (f_abs > 0.) {
00053 if (mf_re > 0.) {
00054 f_re = sqrt(0.5 * (f_abs + mf_re));
00055 f_im = 0.5 * mf_im / f_re;
00056 } else {
00057 f_im = sqrt(0.5 * (f_abs - mf_re));
00058 if (mf_im < 0.) f_im = -f_im;
00059 f_re = 0.5 * mf_im / f_im;
00060 }
00061 }
00062 }
00063
00064 return CTBcomplex<T>(f_re, f_im);
00065 }
00066
00067
00069
00070 template <class T>
00071 static inline void sincos(T& f_sin, T& f_cos, T f_x)
00072 {
00073 f_sin = CTBsin(f_x);
00074 f_cos = CTBcos(f_x);
00075 return;
00076 }
00077
00078
00080
00081 template <class T>
00082 static inline void sinhcosh(T& f_sinh, T& f_cosh, T f_x)
00083 {
00084 T f_expp = CTBexp(f_x);
00085 T f_expm = 1./f_expp;
00086 f_sinh = 0.5 * (f_expp - f_expm);
00087 f_cosh = 0.5 * (f_expp + f_expm);
00088 return;
00089 }
00090
00091
00093
00100 template <class T>
00101 static inline void sinhcosh_red(T& f_sinh, T& f_cosh, T f_x)
00102 {
00103 T f_xabs = CTBabs(f_x);
00104 T f_expm = (f_xabs < 25.) ? CTBexp(-2.*f_xabs) : 0.;
00105 f_sinh = CTBsign(1. - f_expm, f_x);
00106 f_cosh = 1. + f_expm;
00107 return;
00108 }
00109
00110
00112
00113 template <class T>
00114 CTBcomplex<T> CTBcomplex<T>::Exp() const
00115 {
00116 T f_mag = 1.;
00117 T f_re = 1.;
00118 T f_im = 0.;
00119
00120 if (mf_re != 0.) f_mag = CTBexp(mf_re);
00121 if (mf_im != 0.) sincos(f_im, f_re, mf_im);
00122
00123 return CTBcomplex<T>(f_mag*f_re, f_mag*f_im);
00124 }
00125
00126
00128
00129 template <class T>
00130 CTBcomplex<T> CTBcomplex<T>::Log() const
00131 {
00132 return CTBcomplex<T>(CTBlog(Abs()),Arg());
00133 }
00134
00135
00137
00138 template <class T>
00139 CTBcomplex<T> CTBcomplex<T>::Sin() const
00140 {
00141 T f_sin_re = 0.;
00142 T f_cos_re = 1.;
00143 T f_sinh_im = 0.;
00144 T f_cosh_im = 1.;
00145
00146 if (mf_re != 0.) sincos(f_sin_re, f_cos_re, mf_re);
00147 if (mf_im != 0.) sinhcosh(f_sinh_im,f_cosh_im, mf_im);
00148
00149 return CTBcomplex<T>(f_sin_re*f_cosh_im, f_cos_re*f_sinh_im);
00150 }
00151
00152
00154
00155 template <class T>
00156 CTBcomplex<T> CTBcomplex<T>::Cos() const
00157 {
00158 T f_sin_re = 0.;
00159 T f_cos_re = 1.;
00160 T f_sinh_im = 0.;
00161 T f_cosh_im = 1.;
00162
00163 if (mf_re != 0.) sincos(f_sin_re, f_cos_re, mf_re);
00164 if (mf_im != 0.) sinhcosh(f_sinh_im, f_cosh_im, mf_im);
00165
00166 return CTBcomplex<T>(f_cos_re*f_cosh_im, -f_sin_re*f_sinh_im);
00167 }
00168
00169
00171
00172 template <class T>
00173 CTBcomplex<T> CTBcomplex<T>::Tan() const
00174 {
00175 T f_sin_re = 0.;
00176 T f_cos_re = 1.;
00177 T f_sinh_im = 0.;
00178 T f_cosh_im = 1.;
00179
00180 if (mf_re != 0.) sincos(f_sin_re, f_cos_re, mf_re);
00181 if (mf_im != 0.) sinhcosh_red(f_sinh_im, f_cosh_im, mf_im);
00182
00183 CTBcomplex<T> z_sin(f_sin_re*f_cosh_im, f_cos_re*f_sinh_im);
00184 CTBcomplex<T> z_cos(f_cos_re*f_cosh_im, -f_sin_re*f_sinh_im);
00185
00186 return z_sin/z_cos;
00187 }
00188
00189
00191
00192 template <class T>
00193 CTBcomplex<T> CTBcomplex<T>::Asin() const
00194 {
00195 return CTBtimesI(CTBlog(-CTBtimesI(*this) + CTBsqrt((T)1.-CTBpow2(*this))));
00196 }
00197
00198
00200
00201 template <class T>
00202 CTBcomplex<T> CTBcomplex<T>::Acos() const
00203 {
00204 return - CTBtimesI(CTBlog(*this + CTBtimesI(CTBsqrt((T)1.-CTBpow2(*this)))));
00205 }
00206
00207
00209
00210 template <class T>
00211 CTBcomplex<T> CTBcomplex<T>::Atan() const
00212 {
00213 CTBcomplex<T> i(0.,1.);
00214
00215 return (T)0.5 * CTBtimesI( CTBlog((i + *this) / (i - *this) ));
00216 }
00217
00218
00220
00221 template <class T>
00222 CTBcomplex<T> CTBcomplex<T>::Sinh() const
00223 {
00224 T f_sinh_re = 0.;
00225 T f_cosh_re = 1.;
00226 T f_sin_im = 0.;
00227 T f_cos_im = 1.;
00228
00229 if (mf_re != 0.) sinhcosh(f_sinh_re,f_cosh_re, mf_re);
00230 if (mf_im != 0.) sincos(f_sin_im, f_cos_im, mf_im);
00231
00232 return CTBcomplex<T>(f_sinh_re*f_cos_im, f_cosh_re*f_sin_im);
00233 }
00234
00235
00237
00238 template <class T>
00239 CTBcomplex<T> CTBcomplex<T>::Cosh() const
00240 {
00241 T f_sinh_re = 0.;
00242 T f_cosh_re = 1.;
00243 T f_sin_im = 0.;
00244 T f_cos_im = 1.;
00245
00246 if (mf_re != 0.) sinhcosh(f_sinh_re, f_cosh_re, mf_re);
00247 if (mf_im != 0.) sincos(f_sin_im, f_cos_im, mf_im);
00248
00249 return CTBcomplex<T>(f_cosh_re*f_cos_im, f_sinh_re*f_sin_im);
00250 }
00251
00252
00254
00255 template <class T>
00256 CTBcomplex<T> CTBcomplex<T>::Tanh() const
00257 {
00258 T f_sinh_re = 0.;
00259 T f_cosh_re = 1.;
00260 T f_sin_im = 0.;
00261 T f_cos_im = 1.;
00262
00263 if (mf_re != 0.) sinhcosh_red(f_sinh_re, f_cosh_re, mf_re);
00264 if (mf_im != 0.) sincos(f_sin_im, f_cos_im, mf_im);
00265
00266 CTBcomplex<T> z_sinh(f_sinh_re*f_cos_im, f_cosh_re*f_sin_im);
00267 CTBcomplex<T> z_cosh(f_cosh_re*f_cos_im, f_sinh_re*f_sin_im);
00268
00269 return z_sinh/z_cosh;
00270 }
00271
00272
00274
00275 template <class T>
00276 CTBcomplex<T> CTBcomplex<T>::Asinh() const
00277 {
00278 return CTBlog(*this + CTBsqrt(CTBpow2(*this) + (T)1.));
00279 }
00280
00281
00283
00284 template <class T>
00285 CTBcomplex<T> CTBcomplex<T>::Acosh() const
00286 {
00287 return CTBlog(*this + CTBsqrt(CTBpow2(*this) - (T)1.));
00288 }
00289
00290
00292
00293 template <class T>
00294 CTBcomplex<T> CTBcomplex<T>::Atanh() const
00295 {
00296 return (T)0.5 * CTBlog( ((T)1. + *this) / ((T)1. - *this));
00297 }
00298
00299
00301
00302 template <class T>
00303 CTBcomplex<T> CTBcomplex<T>::Pow(int i_y) const
00304 {
00305 CTBcomplex<T> z_f(1.);
00306 int i_nmul = CTBabs(i_y);
00307
00308 for (int i = 0; i < i_nmul; i++) z_f *= *this;
00309 if (i_y < 0) z_f = (T)1./z_f;
00310
00311 return z_f;
00312 }
00313
00314
00316
00317 template <class T>
00318 CTBcomplex<T> CTBcomplex<T>::Pow(const CTBcomplex<T>& z_y) const
00319 {
00320 return CTBexp(z_y * CTBlog(*this));
00321 }
00322
00323
00336 template <class T>
00337 CTBcomplex<T> CTBcomplex<T>::Divide(const CTBcomplex<T>& z_den) const
00338 {
00339 T f_re;
00340 T f_im;
00341
00342 if (fabs(z_den.mf_re) >= fabs(z_den.mf_im)) {
00343 T f_t1 = z_den.mf_im / z_den.mf_re;
00344 T f_t2 = 1./ (z_den.mf_re + f_t1 * z_den.mf_im);
00345 f_re = (mf_re + f_t1 * mf_im) * f_t2;
00346 f_im = (mf_im - f_t1 * mf_re) * f_t2;
00347
00348 } else {
00349 T f_t1 = z_den.mf_re / z_den.mf_im;
00350 T f_t2 = 1. / (f_t1 * z_den.mf_re + z_den.mf_im);
00351 f_re = (f_t1 * mf_re + mf_im) * f_t2;
00352 f_im = (f_t1 * mf_im - mf_re) * f_t2;
00353 }
00354
00355 return CTBcomplex<T>(f_re, f_im);
00356 }
00357
00358
00363 template <class T>
00364 CTBcomplex<T> CTBcomplex<T>::Invert(T f_nom) const
00365 {
00366 T f_re;
00367 T f_im;
00368
00369 if (fabs(mf_re) >= fabs(mf_im)) {
00370 T f_t1 = mf_im / mf_re;
00371 T f_t2 = 1./ (mf_re + f_t1 * mf_im);
00372 f_re = f_nom * f_t2;
00373 f_im = - f_nom * f_t1 * f_t2;
00374
00375 } else {
00376 T f_t1 = mf_re / mf_im;
00377 T f_t2 = 1./ (f_t1 * mf_re + mf_im);
00378 f_re = f_nom * f_t1 * f_t2;
00379 f_im = - f_nom * f_t2;
00380 }
00381
00382 return CTBcomplex<T>(f_re, f_im);
00383 }
00384
00385
00387
00388 template <class T>
00389 void CTBcomplex<T>::ToStream(ostream& os) const
00390 {
00391 int i_width = os.width();
00392
00393 os << setw(0) << "(" << setw(i_width) << mf_re
00394 << "," << setw(i_width) << mf_im << ")";
00395 return;
00396 }
00397
00398
00400
00404 template <class T>
00405 void CTBcomplex<T>::FromStream(istream& is)
00406 {
00407 T f_re;
00408 T f_im;
00409 char c_char;
00410
00411 if (!is) return;
00412
00413 is >> c_char;
00414 if (c_char != '(') {
00415 is.setstate(ios::failbit);
00416 return;
00417 }
00418
00419 is >> f_re;
00420 if (!is) return;
00421
00422 is >> c_char;
00423
00424 if (c_char == ',') {
00425 is >> f_im;
00426 if (!is) return;
00427 is >> c_char;
00428 }
00429
00430 if (c_char != ')') {
00431 is.setstate(ios::failbit);
00432 return;
00433 }
00434
00435 mf_re = f_re;
00436 mf_im = f_im;
00437
00438 return;
00439 }
00440