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
1.2.7