Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

parameters.cc

Go to the documentation of this file.
00001 // parameters.cc
00002 // Illustration of the parameter classes.
00003 
00004 // A "parameter" is a special form of scalar object (real or complex)
00005 // which acts just like any other scalar object in a C++ expression.
00006 // It has a couple of added features over a simple variable of type
00007 // double or complex, however, including:
00008 //
00009 //   (1) The ability to "shadow", or hold a pointer to, another
00010 //       "parameter"-like variable, so that changes to that variable
00011 //       are automatically transferred to the shadowing variable.
00012 //
00013 //   (2) The ability to hold range limits, so that its value will
00014 //       remain within a valid range regardless of attempts to set it
00015 //       to a value outside of that range.
00016 //
00017 // This program will illustrate some of the features of the parameter
00018 // classes which are used extensively throughout the SuperMix library.
00019 
00020 // The header files defining the parameter classes are found in the
00021 // parameter/ subdirectory of the SuperMix include/ directory. The
00022 // header files include:
00023 //
00024 //   abstract_real_parameter.h
00025 //   abstract_complex_parameter.h
00026 //      The interfaces which provide for read access to all parameter-
00027 //      like classes.
00028 //
00029 //   real_parameter.h
00030 //   complex_parameter.h
00031 //      The definitions of the basic parameter classes, real_parameter
00032 //      and complex_parameter.
00033 //
00034 //   function_real_parameter.h
00035 //   scaled_real_parameter.h
00036 //      Definitions of occasionally-useful classes derived from class
00037 //      abstract_real_parameter, these objects may be shadowed by
00038 //      parameter objects.
00039 //
00040 // The following header files are in the main SuperMix include/
00041 // directory and provide additional abstract parameter types:
00042 //
00043 //   parameter.h
00044 //      Since the real_parameter class is the most often used type, this
00045 //      header file typedefs this class to the type "parameter".
00046 //
00047 //   real_interp.h
00048 //   complex_interp.h
00049 //      Provide abstract parameter types that determine their current
00050 //      value by interpolating into a table of values using some variable
00051 //      of type double as an interpolation index.
00052 //
00053 //   simple_error_func.h
00054 //      Classes derived from simple_error_func have a member function
00055 //      called "vary()" which returns a pointer to an abstract parameter
00056 //      which can control the value of some other parameter through the
00057 //      shadowing mechanism. This is the means by which the error
00058 //      function classes controlled by an optimizer actually control the
00059 //      behavior of a simulation. See the example lna/lna_opt.cc
00060 
00061 #include "supermix.h"
00062   
00063 
00064 int main()
00065 {
00066   // *******************************************************************
00067   // Basic declarations and use in statements:
00068 
00069   parameter a;   // variable a behaves like a double in C++ statements
00070 
00071   // can assign double values to a, just like a double:
00072   a = 10.0;
00073   cout << "a = " << a << endl;    // output: "a = 10"
00074 
00075   // can use a in an expression, just like a double:
00076   double b = sqrt(a+6);
00077   cout << "b = " << b << endl;    // output: "b = 4"
00078 
00079   // however, a isn't really a double, so we must cast it if we use ?: :
00080   b = (b > 6) ? double(a) : 6;
00081   cout << "b = " << b << endl;    // output: "b = 6"
00082 
00083   // instead of a cast, we can call the member function get(), which
00084   // returns the value of the parameter:
00085   b = (a > 6) ? a.get() : 6;
00086   cout << "b = " << b << endl;    // output: "b = 10"
00087 
00088   // Here's a complex-number parameter:
00089   complex_parameter z = 3.0 + 4.0*I;
00090   cout << "z = " << z << ", |z| = " << abs(z) << endl;
00091                                   // output: "z = 3+i4, |z| = 5"
00092 
00093   // *******************************************************************
00094   // Using range limits on the real_parameter class:
00095 
00096   // let's assign a maximum limit to parameter a:
00097   a.set_max(6.0);
00098   cout << "a = " << a << endl;    // output: "a = 6"
00099 
00100   // we now can't set a to any value higher than the limit. No complaints
00101   // are issued, a just silently limits itself:
00102   a = 30;
00103   cout << "a = " << a << endl;    // output: "a = 6"
00104 
00105   // ditto for a lower limit:
00106   a.set_min(-1.5);
00107   a = -100;
00108   cout << "a = " << a << endl;    // output: "a = -1.5"
00109 
00110   // we can turn the limiting back off:
00111   a.no_min();
00112   a.no_max();
00113   a = 30;
00114   cout << "a = " << a << endl;    // output: "a = 30"
00115   a = -100;
00116   cout << "a = " << a << endl;    // output: "a = -100"
00117 
00118   // range limiting is not available on the complex_parameter class
00119 
00120 
00121   // *******************************************************************
00122   // Shadowing another parameter-like object
00123 
00124   // setting one parameter equal to another makes it a clone of the other
00125   parameter c = a;
00126   cout << "c = " << c << endl;    // output: "c = -100"
00127   // subsequently changing a won't affect the value of c
00128   a = 2;
00129   cout << "a = " << a << ", c = " << c << endl;
00130                                   // output: "a = 2, c = -100"
00131   
00132   // assigning the address of a to c makes c shadow a:
00133   c = & a;
00134   cout << "a = " << a << ", c = " << c << endl;
00135                                   // output: "a = 2, c = 2"
00136   // now changing a also changes the value returned by c
00137   a = -5;
00138   cout << "a = " << a << ", c = " << c << endl;
00139                                   // output: "a = -5, c = -5"
00140 
00141   // here's another parameter, which shadows c
00142   parameter d(&c);
00143   // now d also tracks a's value, which it gets from c
00144   a = 10;
00145   cout << "a = " << a << ", c = " << c << ", d = " << d << endl;
00146                                   // output: "a = 10, c = 10, d = 10"
00147 
00148   c = 3;
00149   // now c no longer shadows a, but d still shadows c
00150   cout << "a = " << a << ", c = " << c << ", d = " << d << endl;
00151                                   // output: "a = 10, c = 3, d = 3"
00152 
00153   // assigning a = d makes a a clone of d, so a shadows c also:
00154   a = d;
00155   c = 20;
00156   cout << "c = " << c << ", d = " << d << ", a = " << a << endl;
00157                                   // output: "c = 20, d = 20, a = 20"
00158 
00159   // changing d now doesn't affect a, because it shadows c (since that's
00160   // what d was doing at the time of the "a = d" statement)
00161   d = 10;
00162   c = -5;
00163   cout << "c = " << c << ", d = " << d << ", a = " << a << endl;
00164                                   // output: "c = -5, d = 10, a = -5"
00165 
00166   // If you set limits on a parameter, it applies them to the shadowed
00167   // value. Here a and d both shadow c; d will have a limit:
00168   d.set_min(0);
00169   d = & c;
00170   c = 3;
00171   cout << "c = " << c << ", d = " << d << ", a = " << a << endl;
00172                                   // output: "c = 3, d = 3, a = 3"
00173   c = -2;
00174   cout << "c = " << c << ", d = " << d << ", a = " << a << endl;
00175                                   // output: "c = -2, d = 0, a = -2"
00176   c = 10;
00177   cout << "c = " << c << ", d = " << d << ", a = " << a << endl;
00178                                   // output: "c = 10, d = 10, a = 10"
00179 
00180 
00181   // *******************************************************************
00182   // Special features of complex_parameter objects
00183 
00184   // complex_parameters can shadow one another:
00185   complex_parameter u(&z);
00186   z = 2 + I*6;
00187   cout << "z = " << z << ", u = " << u << endl;
00188                                   // output: "z = 2+i6, u = 2+i6"
00189 
00190   // complex_parameters can also shadow real_parameters; here's a chain
00191   // of shadowing:
00192   z = & a;    // u -> z -> a -> c;
00193   c = 5;
00194   cout << "c = " << c << ", z = " << z << ", u = " << u << endl;
00195                                   // output: "c = 5, z = 5+i0, u = 5+i0"
00196 
00197   // a special constructor lets you have a complex_parameter shadow
00198   // TWO real parameters:
00199   u = complex_parameter(c,d);  // now u = c + I*d, as c and d vary
00200   c = 3; d = 4;
00201   cout << "c = " << c << ", d = " << d << ", u = " << u << endl;
00202                                   // output: "c = 3, d = 4, u = 3+i4"
00203   c = -5; d = 10;
00204   cout << "c = " << c << ", d = " << d << ", u = " << u << endl;
00205                                   // output: "c = -5, d = 10, u = -5+i10"
00206 
00207   // Now we can provide range limiting for u by limiting the ranges
00208   // on c and d:
00209   c.set_min(0).set_max(3);  // note that we can concatenate limit commands
00210   d.set_min(-1).set_max(1);
00211   cout << "c = " << c << ", d = " << d << ", u = " << u << endl;
00212                                   // output: "c = 0, d = 1, u = 0+i1"
00213   c = 2; d = 0.5;
00214   cout << "c = " << c << ", d = " << d << ", u = " << u << endl;
00215                                   // output: "c = 2, d = 0.5, u = 2+i0.5"
00216 
00217   // we can also construct the complex value using polar form rather
00218   // than cartesian; note the special 3rd argument in the constructor
00219   c.no_max();           // minimum for c is still 0.0
00220   d.no_min().no_max();
00221   u = complex_parameter(c,d, complex_parameter::POLAR);
00222   c = 2;
00223   d = 90*Degree;  // convert a number to radians by multiplying by Degree
00224   cout << "c = " << c << ", d = " << d << ", u = " << u << endl;
00225                         // output: "c = 2, d = 1.5708, u = 1.22465e-16+i2"
00226   // (note: the double precision calculation gives u a tiny real part)
00227 
00228   // let's display u in (magnitude,degree) form:
00229   complex::out_degree();          // output format: magnitude degree
00230   complex::out_delimited();       // use (,) as delimiters
00231   cout << "u = " << u << endl;    // output: "u = (2,90)"
00232 
00233 }

Please direct comments and corrections to supermix@submm.caltech.edu
Go to the supermix home page
Generated by doxygen1.2.7