00001 // SuperMix version 1.0 C++ source file
00002 //
00003 // Copyright (c) 1999 California Institute of Technology.
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms for noncommercial
00007 // purposes are permitted provided that the above copyright notice and
00008 // this paragraph are duplicated in all such forms and that any
00009 // documentation and other materials related to such distribution and
00010 // use acknowledge that the software was developed by California
00011 // Institute of Technology. Redistribution and/or use in source or
00012 // binary forms is not permitted for any commercial purpose. Use of
00013 // this software does not include a permitted use of the Institute's
00014 // name or trademark for any purpose.
00015 //
00016 // DISCLAIMER:
00017 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT
00018 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR
00019 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET
00020 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
00021 // LICENSED PRODUCT, HOWEVER USED. IN NO EVENT SHALL CALTECH/JPL BE
00022 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO
00023 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC
00024 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF
00025 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN
00026 // FACT SHALL KNOW OF THE POSSIBILITY. THE USER BEARS ALL RISK
00027 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED
00028 // MATERIALS.
00029 //
00030 // ********************************************************************
00031 // SIScmplx.h
00032 // complex data type and functions upon it
00033 //
00034 // *** NOT THE SAME AS THE STROUSTRUP COMPLEX CLASS ***
00035 //
00036 // F. Rice 7/8/97
00037 //
00038 // 4/24/00: Added abs(double) as a inline equivalent for fabs()
00039 // 9/27/99: Added the db io_mode; added dtoz(), a real->z converter
00040 // 11/10/98: Put <math.h> back in; added inverse trig and hypb fcns
00041 // 7/28/98: Moved some operations into SIScmplx.cc; no longer includes
00042 // <iostream.h> or <math.h>; major output enhancements
00043 // 7/15/98: Fixed overloaded operators for use with register variables
00044 // 7/7/98: Moved initializers out of constuctor bodies.
00045 // 1/30/98: Added >> operator overloading to read complex numbers.
00046 // 10/15/97: Fixed a problem with CC compiles by getting rid of default
00047 // operator = (now is sure to return Lvalues as required).
00048 // 9/19/97: Added complex sqrt().
00049 // 9/9/97: Major revisions to improve compatibility and functionality
00050 // 8/12/97: Added magnitude squared function.
00051 // 7/30/97: Overloaded iostream << operator. Fully tested.
00052 // 7/29/97: Changed name of this file to SIScmplx.h from complex.h
00053 // All functionality full tested.
00054 // 7/29/97: Added assignment operators, unary plus, zarg.
00055 // Loads its own math.h. Now does conditional loading using
00056 // #ifndef/#define/#endif.
00057 // 7/11/97: added unary -, relational ops.
00058 // 7/10/97: no longer needs complex.cc - all fcns in this header
00059 // 7/8/97: basic functionality
00060 //
00061 // ********************************************************************
00062 //
00063 // The complex data type consists of two (public) doubles.
00064 // The following operations are defined by this file:
00065 //
00066 // (z: complex; d: double; n:int)
00067 //
00068 //
00069 // Basic creation, access, and assignment:
00070 // Note that "complex" is an alias for "Complex" (using typedef)
00071 //
00072 // Complex z; create z with initial value 0 + 0 I
00073 // Complex z(d); initial value d + 0 I
00074 // Complex z(d1,d2); initial value d1 + d2 I
00075 //
00076 // z.real; access parts of z (each a double)
00077 // z.imaginary; (these are lvalues)
00078 //
00079 // real(z); read parts of z (each a double)
00080 // imag(z); (these are rvalues)
00081 //
00082 // z = z1; assign values to z
00083 // z = Complex(d1,d2); z = d1 + d2 I
00084 // z = d;
00085 // z = n; (for the last 2 cases, z.imaginary = 0.0)
00086 //
00087 //
00088 // Arithmetic operators:
00089 //
00090 // z = z1 + z2; z = z1 - z2;
00091 // z = z1 + d; z = d + z1; z = z1 - d; z = d - z1;
00092 // z = z1 + n; z = n + z1; z = z1 - n; z = n - z1;
00093 //
00094 // z = z1 * z2; z = z1 / z2;
00095 // z = z1 * d; z = d * z1; z = z1 / d; z = d / z1;
00096 // z = z1 * n; z = n * z1; z = z1 / n; z = n / z1;
00097 //
00098 // z = -z1; unary minus
00099 // z = +z1; unary plus
00100 //
00101 //
00102 // Additional assignment operators:
00103 //
00104 // z += z1; z -= z1; z *= z1; z /= z1;
00105 // z += d; z -= d; z *= d; z /= d;
00106 // z += n; z -= n; z *= n; z /= n;
00107 //
00108 //
00109 // Relational operators:
00110 //
00111 // z == z1; z != z1;
00112 // z == d; z != d; needs z.imaginary == 0.0 for z == d
00113 //
00114 //
00115 // Other functions:
00116 //
00117 // z = polar(rho,theta); construct z from polar form (doubles)
00118 // z = conj(z1), zconj(z1); complex conjugate of z1
00119 // d = abs(z1), zabs(z); magnitude of z
00120 // d = arg(z1), zarg(z); argument (phase) of z, in range: +/- Pi
00121 // d = norm(z1), zmagsq(z); magnitude of z squared (z*z)
00122 // z = sqrt(z1); square root, arg(z) will be in +/- Pi/2
00123 // z = log(z1); z = exp(z1); complex log and exponential
00124 // z = log10(z1); complex common log (base 10)
00125 // z = pow(z1,d); raise complex to a power (double)
00126 // z = pow(z1,z2); (or complex)
00127 // trig and hyperbolic functions:
00128 // cos(z), sin(z), tan(z), cosh(z), sinh(z), tanh(z)
00129 // inverses:
00130 // acos(z), asin(z), atan(z), acosh(z), asinh(z), atanh(z)
00131 //
00132 // (note that C++ will cast a d or n to Complex if used as an argument
00133 // to functions which require type Complex, with imaginary part = 0.0)
00134 //
00135 // ********************************************************************
00136 //
00137 // Complex number input/output and formatting
00138 //
00139 // Stream operators:
00140 //
00141 // <ostream> << z; writes z, using a format etablished by functions
00142 // described below
00143 //
00144 // <istream> >> z; reads z, interpreting the input as described below
00145 //
00146 //
00147 // I/O modes:
00148 //
00149 // There are several i/o modes, declared in the enumerated type
00150 // Complex::io_mode.
00151 //
00152 // cartesian: the real part followed by the complex part (the default)
00153 // polar: the magnitude followed by the phase in radians
00154 // degree: the magnitude followed by the phase in degrees
00155 // db: 20*log10(magnitude) followed by phase in degrees
00156 //
00157 // Setting the output mode:
00158 //
00159 // Complex::out_cartesian(); set output mode to cartesian
00160 // Complex::out_polar(); set output mode to polar
00161 // Complex::out_degree(); set output mode to degree
00162 // Complex::out_db(); set output mode to db
00163 // Complex::out_mode(m); set output mode m (type Complex::io_mode)
00164 // Complex::out_mode(); just report the current output mode
00165 //
00166 // each of the above functions returns the previous output mode
00167 //
00168 // Output prefix, separator, and suffix strings:
00169 //
00170 // The pair of numeric values to be output can be preceeded by an
00171 // optional character string prefix, whose default value is empty. The
00172 // pair may be followed by an optional suffix as well. The separator
00173 // string to be inserted between the pair of values may also be
00174 // specified; its default value is determined by the output mode and
00175 // is described below.
00176 //
00177 // Setting the output strings:
00178 //
00179 // Complex::out_prefix(s); set the prefix to s
00180 // Complex::out_suffix(s); set the suffix to s
00181 // Complex::out_separator(s); set the separator to s
00182 //
00183 // s may be a singe char, a C-style char string, or a C++ string type.
00184 // The default value for s is an empty string. Each of the above
00185 // functions returns a copy of the previous value for its string.
00186 // Each of the above functions with no argument simply returns the
00187 // current value for its string.
00188 //
00189 // The default value (empty string) for the output separator causes the
00190 // following output between the pair of numeric values in the Complex
00191 // number:
00192 //
00193 // Output mode polar or degree: a single space separates the pair.
00194 // Output mode cartesian: for z.imaginary >= 0, the separator is "+i";
00195 // for z.imaginary < 0, the separator is "-i", and the absolute value
00196 // of the imaginary part is output.
00197 //
00198 // More ways to set the output prefix, suffix, and separator:
00199 //
00200 // Complex::out_default(); set all strings to the default (empty)
00201 // Complex::out_space(); set the separator to " ", others empty
00202 // Complex::out_delimited(); set the strings to "("; ","; ")"
00203 //
00204 // these functions do not return anything.
00205 //
00206 //
00207 // Setting the input mode:
00208 //
00209 // Complex::in_cartesian(); set input mode to cartesian
00210 // Complex::in_polar(); set input mode to polar
00211 // Complex::in_degree(); set input mode to degree
00212 // Complex::in_db(); set input mode to db
00213 // Complex::in_mode(m); set input mode m (type Complex::io_mode)
00214 // Complex::in_mode(); just report the current input mode
00215 //
00216 // each of the above functions returns the previous input mode
00217 //
00218 // A function to convert two reals to a complex, using the current input
00219 // mode in order to interpret the arguments as though they had been input
00220 // in order from a stream using <<:
00221 //
00222 // dtoz(double d1, double d2); return complex formed from the two doubles
00223 //
00224 // The input format options:
00225 //
00226 // The default input format requires two whitespace-separated doubles
00227 // for each complex number input; the two doubles are converted into
00228 // a single complex z.
00229 //
00230 // The "delimited" input format reads any of the three input forms:
00231 //
00232 // x (x) (x,y)
00233 //
00234 // The first two forms convert the single double x into complex z with
00235 // z.real = x, z.imaginary = 0; the third form converts the two doubles
00236 // x and y into a single complex z. Whitespace may optionally separate
00237 // the various parts of the delimited forms.
00238 //
00239 // For both the default and delimited input forms, two doubles are
00240 // converted to a complex number as follows:
00241 //
00242 // If the input mode is cartesian, two doubles are interpreted as the
00243 // real part of z followed by the imaginary part of z. Otherwise,
00244 // the first double is interpreted as the magnitude of z, the second
00245 // as the phase of z, in either radians
00246 // (polar) or degrees (degree or db).
00247 //
00248 // Setting the input form:
00249 //
00250 // Complex::in_form(f); set input form to f
00251 // (0: default; 1: delimited)
00252 // returns the previous value for the input form
00253 //
00254 // Complex::in_default(); set default input form
00255 // Complex::in_delimited(); set delimited input form
00256 //
00257 // Complex::in_form(); read the current input form
00258 //
00259 //
00260 // ********************************************************************
00261
00262 #ifndef SISCOMPLEX_H
00263 #define SISCOMPLEX_H 1
00264
00265 class ostream;
00266 class istream;
00267 #include <math.h>
00268 #include <string>
00269
00270 //---------------------------------------------------------------------
00271 // An alias for fabs() which is consistent with abs(complex):
00272
00273 inline double abs(double d) { return fabs(d); }
00274
00275 //---------------------------------------------------------------------
00276 // The Complex class:
00277
00278 class Complex {
00279 public:
00280
00281 //the data:
00282
00283 double real, imaginary;
00284
00285
00286 //constructors:
00287
00288 Complex(void) : real(0.0), imaginary(0.0) { }
00289
00290 //(uses default copy constructor, Complex(Complex) )//
00291
00292 Complex(double r, double i = 0.0) : real(r), imaginary(i) { }
00293
00294
00295 //assignment:
00296
00297 inline Complex & operator =(const Complex & z)
00298 {
00299 real = z.real;
00300 imaginary = z.imaginary;
00301 return *this;
00302 }
00303
00304 inline Complex & operator =(const double d)
00305 {
00306 real = d;
00307 imaginary = 0;
00308 return *this;
00309 }
00310
00311 inline Complex & operator =(const int n)
00312 {
00313 real = n;
00314 imaginary = 0;
00315 return *this;
00316 }
00317
00318
00319 // i/o formatting:
00320
00321 enum io_mode {cartesian = 0, polar = 1, degree = 2, db = 3};
00322
00323 static io_mode out_mode(); // return the current output mode
00324 static io_mode out_mode(io_mode m); // change to mode m; return previous
00325 static inline io_mode out_polar() { return out_mode(polar); }
00326 static inline io_mode out_degree() { return out_mode(degree); }
00327 static inline io_mode out_db() { return out_mode(db); }
00328 static inline io_mode out_cartesian() { return out_mode(cartesian); }
00329
00330 static string out_prefix(); // return the current output prefix
00331 static string out_prefix(const string &);
00332 static string out_prefix(const char * const);
00333 static string out_prefix(const char);
00334
00335 static string out_separator(); // return the current output separator
00336 static string out_separator(const string &);
00337 static string out_separator(const char * const);
00338 static string out_separator(const char);
00339
00340 static string out_suffix(); // return the current output suffix
00341 static string out_suffix(const string &);
00342 static string out_suffix(const char * const);
00343 static string out_suffix(const char);
00344
00345 static void out_default();
00346 static void out_space();
00347 static void out_delimited();
00348
00349 static io_mode in_mode(); // return the current input mode
00350 static io_mode in_mode(io_mode m); // change to mode m; return previous
00351 static inline io_mode in_polar() { return in_mode(polar); }
00352 static inline io_mode in_degree() { return in_mode(degree); }
00353 static inline io_mode in_db() { return in_mode(db); }
00354 static inline io_mode in_cartesian() { return in_mode(cartesian); }
00355
00356 static int in_form(); // report current input format (0 == default)
00357 static int in_form(int f); // set delimited input if f != 0, else default
00358 static inline int in_default() { return in_form(0); }
00359 static inline int in_delimited() { return in_form(1); }
00360
00361
00362 //destructor:
00363
00364 //(uses default destructor)//
00365
00366 };
00367
00368 //---------------------------------------------------------------------
00369 //Access functions: real(), imag():
00370
00371 inline double real( const Complex & z ) { return z.real; }
00372
00373 inline double imag( const Complex & z ) { return z.imaginary; }
00374
00375
00376 //---------------------------------------------------------------------
00377 // Construct from polar form: polar():
00378
00379 inline Complex polar( const double rho , const double theta )
00380 {
00381 return Complex (rho * cos(theta), rho * sin(theta));
00382 }
00383
00384
00385 //---------------------------------------------------------------------
00386 // Conjugation: zconj(), conj():
00387
00388 inline Complex zconj( const Complex & z )
00389 {
00390 return Complex (z.real, -z.imaginary);
00391 }
00392
00393 inline Complex conj( const Complex & z ) { return zconj(z); }
00394
00395 //---------------------------------------------------------------------
00396 // Basic Math Operator Overloading:
00397
00398 // addition:
00399
00400 inline Complex operator +(const Complex & z1, const Complex & z2)
00401 {
00402 return Complex (z1.real+z2.real, z1.imaginary+z2.imaginary);
00403 }
00404
00405 inline Complex operator +(const Complex & z, const double d)
00406 {
00407 return Complex (z.real+d, z.imaginary);
00408 }
00409
00410 inline Complex operator +(const double d, const Complex & z)
00411 {
00412 return Complex (z.real+d, z.imaginary);
00413 }
00414
00415 inline Complex operator +(const Complex & z, const int n)
00416 {
00417 return Complex (z.real+n, z.imaginary);
00418 }
00419
00420 inline Complex operator +(const int n, const Complex & z)
00421 {
00422 return Complex (z.real+n, z.imaginary);
00423 }
00424
00425
00426 // subtraction:
00427
00428 inline Complex operator -(const Complex & z1, const Complex & z2)
00429 {
00430 return Complex (z1.real-z2.real, z1.imaginary-z2.imaginary);
00431 }
00432
00433 inline Complex operator -(const Complex & z, const double d)
00434 {
00435 return Complex (z.real-d, z.imaginary);
00436 }
00437
00438 inline Complex operator -(const double d, const Complex & z)
00439 {
00440 return Complex (d-z.real, -z.imaginary);
00441 }
00442
00443 inline Complex operator -(const Complex & z, const int n)
00444 {
00445 return Complex (z.real-n, z.imaginary);
00446 }
00447
00448 inline Complex operator -(const int n, const Complex & z)
00449 {
00450 return Complex (n-z.real, -z.imaginary);
00451 }
00452
00453
00454 // unary minus and plus:
00455
00456 inline Complex operator -(const Complex & z)
00457 {
00458 return Complex (-z.real, -z.imaginary);
00459 }
00460
00461 inline Complex operator +(const Complex & z)
00462 {
00463 return z;
00464 }
00465
00466
00467 // multiplication:
00468
00469 inline Complex operator *(const Complex & z1, const Complex & z2)
00470 {
00471 return Complex (z1.real*z2.real - z1.imaginary*z2.imaginary,
00472 z1.imaginary*z2.real + z1.real*z2.imaginary);
00473 }
00474
00475 inline Complex operator *(const Complex & z, const double d)
00476 {
00477 return Complex (z.real*d, z.imaginary*d);
00478 }
00479
00480 inline Complex operator *(const double d, const Complex & z)
00481 {
00482 return Complex (z.real*d, z.imaginary*d);
00483 }
00484
00485 inline Complex operator *(const Complex & z, const int n)
00486 {
00487 return Complex (z.real*n, z.imaginary*n);
00488 }
00489
00490 inline Complex operator *(const int n, const Complex & z)
00491 {
00492 return Complex (z.real*n, z.imaginary*n);
00493 }
00494
00495
00496 // division:
00497
00498 inline Complex operator /(const Complex & z, const double d)
00499 {
00500 return Complex (z.real/d, z.imaginary/d);
00501 }
00502
00503 inline Complex operator /(const Complex & z1, const Complex & z2)
00504 {
00505 return (z1 * zconj(z2))/(z2.real*z2.real + z2.imaginary*z2.imaginary);
00506 }
00507
00508 inline Complex operator /(const double d, const Complex & z)
00509 {
00510 return (zconj(z) * (d/(z.real*z.real + z.imaginary*z.imaginary)));
00511 }
00512
00513 inline Complex operator /(const Complex & z, const int n)
00514 {
00515 return Complex (z.real/n, z.imaginary/n);
00516 }
00517
00518 inline Complex operator /(const int n, const Complex & z)
00519 {
00520 return (zconj(z) * (n/(z.real*z.real + z.imaginary*z.imaginary)));
00521 }
00522
00523 //---------------------------------------------------------------------
00524 // Relational Operator Overloading:
00525
00526 inline int operator ==(const Complex & z1, const Complex & z2)
00527 {
00528 return (z1.real == z2.real) && (z1.imaginary == z2.imaginary);
00529 }
00530
00531 inline int operator !=(const Complex & z1, const Complex & z2)
00532 {
00533 return !(z1 == z2);
00534 }
00535
00536 //---------------------------------------------------------------------
00537 // Assignment Operator Overloading:
00538
00539 // +=
00540
00541 inline Complex & operator +=(Complex & z1, const Complex & z2)
00542 {
00543 z1.real += z2.real;
00544 z1.imaginary += z2.imaginary;
00545 return z1;
00546 }
00547
00548 inline Complex & operator +=(Complex & z, const double d)
00549 {
00550 z.real += d;
00551 return z;
00552 }
00553
00554 inline Complex & operator +=(Complex & z, const int n)
00555 {
00556 z.real += n;
00557 return z;
00558 }
00559
00560
00561 // -=
00562
00563 inline Complex & operator -=(Complex & z1, const Complex & z2)
00564 {
00565 z1.real -= z2.real;
00566 z1.imaginary -= z2.imaginary;
00567 return z1;
00568 }
00569
00570 inline Complex & operator -=(Complex & z, const double d)
00571 {
00572 z.real -= d;
00573 return z;
00574 }
00575
00576 inline Complex & operator -=(Complex & z, const int n)
00577 {
00578 z.real -= n;
00579 return z;
00580 }
00581
00582
00583 // *=
00584
00585 inline Complex & operator *=(Complex & z1, const Complex & z2)
00586 {
00587 z1 = z1 * z2;
00588 return z1;
00589 }
00590
00591 inline Complex & operator *=(Complex & z, const double d)
00592 {
00593 z.real *= d; z.imaginary *= d;
00594 return z;
00595 }
00596
00597 inline Complex & operator *=(Complex & z, const int n)
00598 {
00599 z.real *= n; z.imaginary *= n;
00600 return z;
00601 }
00602
00603
00604 // /=
00605
00606 inline Complex & operator /=(Complex & z1, const Complex & z2)
00607 {
00608 z1 = z1 / z2;
00609 return z1;
00610 }
00611
00612 inline Complex & operator /=(Complex & z, const double d)
00613 {
00614 z.real /= d; z.imaginary /= d;
00615 return z;
00616 }
00617
00618 inline Complex & operator /=(Complex & z, const int n)
00619 {
00620 z.real /= n; z.imaginary /= n;
00621 return z;
00622 }
00623
00624
00625 //---------------------------------------------------------------------
00626 // i/o stream Operator Overloading, and dtoz():
00627
00628 ostream &operator <<(ostream & out_file, Complex z);
00629
00630 istream &operator >>(istream & in_file, Complex & z);
00631
00632 Complex dtoz(double d1, double d2);
00633
00634
00635 //---------------------------------------------------------------------
00636 // Other Useful functions:
00637
00638 // absolute value (magnitude):
00639
00640 double zabs( const Complex & z );
00641
00642 inline double abs( const Complex & z ) { return zabs(z); }
00643
00644
00645 // argument (phase) in +/- Pi:
00646
00647 double zarg( const Complex & z );
00648
00649 inline double arg( const Complex & z ) { return zarg(z); }
00650
00651
00652 // magnitude squared:
00653
00654 inline double zmagsq( const Complex & z )
00655 {
00656 return ( z.real*z.real + z.imaginary*z.imaginary );
00657 }
00658
00659 inline double norm( const Complex & z ) { return zmagsq(z); }
00660
00661
00662 // logs and exponentials:
00663
00664 Complex log( const Complex & z );
00665
00666 Complex exp( const Complex & z );
00667
00668 Complex log10( const Complex & z );
00669
00670
00671 // powers:
00672
00673 Complex pow( const Complex & z, const double d );
00674
00675 Complex pow( Complex z1, const Complex & z2 );
00676
00677 inline Complex sqrt( const Complex & z )
00678 {
00679 return pow(z, 0.5);
00680 }
00681
00682
00683 // trig and hyperbolic functions and inverses:
00684
00685 Complex cos( const Complex & z );
00686
00687 Complex sin( const Complex & z );
00688
00689 Complex tan( Complex z );
00690
00691 Complex cosh( const Complex & z );
00692
00693 Complex sinh( const Complex & z );
00694
00695 Complex tanh( Complex z );
00696
00697 Complex acos( const Complex & z );
00698
00699 Complex asin( const Complex & z );
00700
00701 Complex atan( Complex z );
00702
00703 Complex acosh( const Complex & z );
00704
00705 Complex asinh( const Complex & z );
00706
00707 Complex atanh( Complex z );
00708
00709
00710
00711 //---------------------------------------------------------------------
00712 // Alias for the complex type:
00713 // Comment out the following line if you want to use the standard
00714 // complex type as well:
00715
00716 typedef Complex complex;
00717
00718 //---------------------------------------------------------------------
00719 #endif /* SISCOMPLEX_H */
Please direct comments and corrections to
supermix@submm.caltech.edu
Go to the supermix home page
Generated by
1.2.7