casa
$Rev:20696$
|
00001 //# Quantum.h: class to manipulate physical, dimensioned quantities 00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: Quantum.h 20993 2010-11-08 13:36:32Z gervandiepen $ 00027 00028 #ifndef CASA_QUANTUM_H 00029 #define CASA_QUANTUM_H 00030 00031 00032 //# Includes 00033 #include <casa/aips.h> 00034 #include <casa/Quanta/QBase.h> 00035 #include <casa/iosstrfwd.h> 00036 00037 namespace casa { //# NAMESPACE CASA - BEGIN 00038 00039 //# Forward Declarations 00040 template <class T> class Quantum; 00041 00042 //# Typedefs 00043 typedef Quantum<Double> Quantity; 00044 00045 // <summary> 00046 // Quantities (i.e. dimensioned values) 00047 // </summary> 00048 00049 // <use visibility=export> 00050 00051 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tQuantum"> 00052 // </reviewed> 00053 // 00054 // <prerequisite> 00055 // <li> <linkto class=Unit>Unit</linkto> 00056 // </prerequisite> 00057 // 00058 // <etymology> 00059 // A Quantity is defined as a single Double value with attached units. 00060 // From this definition the templated Quantum class arose, to have non-Double, 00061 // non-scalar quantities. 00062 // </etymology> 00063 // 00064 // <synopsis> 00065 // Quantities are values with a unit. Their basic specification can be one of 00066 // two forms: 00067 // <srcblock> 00068 // Quantity( Double value, String unit); // or: Unit unit 00069 // Quantum<Type> ( Type value, String unit) // or: Unit unit 00070 // </srcblock> 00071 // 00072 // A unit is a string of known unit fields separated 00073 // by 'space' or '.' (to indicate multiply) or '/' (to indicate divide). 00074 // See the <linkto class=Unit>Unit</linkto> class for details. 00075 // 00076 // Example: km/s/(Mpc.s)2 is identical to km.s-1.Mpc-2.s-2 00077 // 00078 // <h3> Defining a Quantum </h3> 00079 // The following list of constructors is available. 00080 // <note role=tip> 00081 // In the following 'String' can be replaced by 'Unit' everywhere. The 00082 // only difference being a check for a legitimate unit string being executed 00083 // if Unit specified (with exception if error) 00084 // </note> 00085 // <note role=tip> 00086 // <src>'Quantum<Type>'</src> can, if Type equals Double, be replaced 00087 // with 'Quantity' 00088 // 00089 // 'Type' can be any simple or non-simple arithmetic type. 00090 // 00091 // E.g. <src><Double>, <Complex>, <Vector<Double> ></src> 00092 // </note> 00093 // <ul> 00094 // <li> <src>Quantum<Type>() value 0 generated</src> 00095 // <li> <src>Quantum<Type>( Quantum<Type>) copy constructor</src> 00096 // <li> <src>Quantum<Type>( Type factor) value factor generated</src> 00097 // <li> <src>Quantum<Type>( Type factor, Unit unit) specified quantity</src> 00098 // <li> <src>Quantum<Type>( Type factor, Quantum<any> quant) specified factor,</src> 00099 // the unit from the quant 00100 // </ul> 00101 // 00102 // 00103 // <h3> Manipulating quantities </h3> 00104 // <linkto group="QMath.h#Quantum mathematical operations">Mathematical operators and functions</linkto> and 00105 // <linkto group="QLogical.h#Quantum logical operations">logical operations</linkto> (comparisons) 00106 // are defined on Quantums. They are, 00107 // of course, only available if the template Type supports them. 00108 // <ul> 00109 // <li> <src>= assignment of identical <type></src> 00110 // <li> <src>* *= multiple two Quantums of same <type>, or Quantum and type</src> 00111 // <li> <src>/ /= divide two Quantums of same <type>, or Quantum and type</src> 00112 // note: 00113 // In multiplication and division, and if <src><type></src> is scalar, the left or 00114 // right-hand side can be of type <src><type></src> (e.g 2.*Quantity is allowed) 00115 // <li> <src>+ += add two Quantums of same <type> or Quantum and type</src> 00116 // and same unit dimensions (else exception) 00117 // <li> - -= subtract (same as +) 00118 // <li> - negate Quantum 00119 // <li> + unary + on Quantum 00120 // <li> <src>== != compare unit dimensions and value of same <type>. They will</src> 00121 // be unequal if the units do not match or the values (possibly 00122 // converted to common base units). All comparisons work also 00123 // on a <src>Quantum<type> and <type></src> 00124 // <li> <src>< > compare unit dimensions. Exception if no match,</src> 00125 // else compare the values 00126 // <li> <src><= >= ibid</src> 00127 // <li> pow(Int) raise to an (integer) power 00128 // </ul> 00129 // 00130 // 00131 // <h3> Manipulating the value and/or units of quanta </h3> 00132 // Quantities can be converted to other units by the following set of member 00133 // functions: 00134 // <ul> 00135 // <li> convert() will convert the quantum to canonical units. 00136 // E.g. given myval=Quantity(5.,"Jy"), 00137 // myval.convert() will convert the qunatum to 00138 // Quantity(5.e-26,"kg.s-2") 00139 // <li> convert(Unit unit) will convert the quantum to the 00140 // specified unit with any remaining dimensions 00141 // expressed in canonical units. E.g given 00142 // myval as above, myval.convert("W/cm") will 00143 // make it Quantity(5.e-28,"W/cm.m-1.s") 00144 // <li> <src>convert(Quantum<Type> quant) will convert the quantum</src> 00145 // to the units of the specified quant with the 00146 // same conversion rules as the previous one 00147 // </ul> 00148 // <note role=tip> All converting type methods (i.e. convert(), get() and 00149 // getValue() with specified units), will automatically convert also from 00150 // time to angle units (or v.v) if necessary, as long as they are simple. I.e. 00151 // deg will be converted to h, but asking to convert m/s to m/deg will 00152 // produce the standard conversion to m/deg.rad/s. </note> 00153 // 00154 // Quanta can be checked for having the correct unit dimensions (e.g. before 00155 // addition or comparing) by the following two member functions, which will 00156 // return a Bool value: 00157 // <ul> 00158 // <li> isConform(Unit unit) 00159 // <li> <src>isConform(Quantum<Type> quant)</src> 00160 // <li> check(UnitVal kind) 00161 // </ul> 00162 // or by an assertion, which will throw an exception:<br> 00163 // <ul> 00164 // <li> assure(UnitVal kind) 00165 // </ul> 00166 // 00167 // The quantum can be retrieved with a change in units by: 00168 // <ul> 00169 // <li> get() will return the quantum converted to canonical units. 00170 // E.g. given myval=Quantity(5.,"Jy"), 00171 // myval.get() will return 00172 // Quantity(5.e-26,"kg.s-2") 00173 // <li> get(Unit unit) will return the quantum converted to the 00174 // specified unit with any remaining dimensions 00175 // expressed in canonical units. E.g given 00176 // myval as above, myval.get("W/cm") will 00177 // return it as Quantity(5.e-28,"W/cm.m-1.s") 00178 // <li> <src>get(Quantum<Type> quant) will return the quantum converted</src> 00179 // to the units of the specified quant with the 00180 // same conversion rules as the previous one 00181 // </ul> 00182 // 00183 // The value and units of a quantum can be set or retrieved separately by the 00184 // following member functions: 00185 // <ul> 00186 // <li> getValue() return the value (as Type) of the quantum. 00187 // <note role=tip> myval.get().getValue() will return the 00188 // value of myval expressed in canonical units 00189 // </note> 00190 // <li> getValue(Unit unit) return the value (as converted to unit) 00191 // <li> getUnit() return the String part of the unit of the 00192 // quantum (use getFullUnit if interested in 00193 // the complete Unit, e.g. for re-use) 00194 // <li> getFullUnit() return the complete unit of the Quantum (use 00195 // getUnit() if interested in String part only) 00196 // <li> setValue(Type val) replace the value of the quantum with val, 00197 // leaving the units the same 00198 // <li> scale(Type val) multiply the value (leaving units same) by the 00199 // specified value 00200 // <li> setUnit(Unit unit) replace the units of the quantum, leaving 00201 // the value the same. 00202 // <li> <src>setUnit(Quantum<Type> quant) ibid</src> 00203 // <li> set(String quantity) replace the value and unit as deduced from quantity 00204 // </ul> 00205 // 00206 // The output operator (<src><<</src>) will produce the value of the quantum and its 00207 // units. Given <src>Quantity myval(5.,"mJy"), << myval</src> will produce: 00208 // <src>5.0 mJy</src>; while <src><< myval.get("yW/m2")</src> 00209 // will produce: <src>.00005 yW/m2.s</src>.<br> 00210 // The input operator (<src>>></src>, or the static read functions) will 00211 // convert a String to a Quantum (quantity only for now). The analysis 00212 // will do the following: 00213 // <ul> 00214 // <li> Check if it can be converted as a time/angle, if so use 00215 // (<linkto class=MVAngle>MVAngle</linkto>) 00216 // <li> Check if it can be used as a date/time. if so use 00217 // (<linkto class=MVTime>MVTime</linkto>) 00218 // <li> Interpret as a value with units 00219 // </ul> 00220 // <note role=caution> Since e.g. <em>12d</em> could be interpreted as 00221 // being both an angle (12 degrees) or a quantity (12 days), the only way 00222 // is to differentiate them with a decimal point (12.d will be days)</note> 00223 // 00224 // </synopsis> 00225 // 00226 // <example> 00227 // An experiment has measured the energy of a photon in keV. The following will 00228 // output the wavelength and frequency of this photon (see the 00229 // <linkto class=QC">QC</linkto> class for quantity constants): 00230 // <srcblock> 00231 // #include <casa/Quanta.h> 00232 // Double myval; // keV photon energy 00233 // Quantity quant(myval,"keV"); // make quantity 00234 // cout << "A photon with energy " << quant << endl 00235 // << " has a frequency of " 00236 // << (quant/QC::h)->get("GHz") << endl // h=Planck 00237 // << " and a wavelength of " 00238 // << (QC::c/quant/QC::h)->get("nm") // c=light velocity 00239 // << " or " << QC::c/quant/QC::h << endl; 00240 // </srcblock> 00241 // </example> 00242 // 00243 // <motivation> 00244 // Major use is foreseen in all calculations with observed data. 00245 // </motivation> 00246 00247 // <templating arg=Qtype> 00248 // <li> prefix +,- 00249 // <li> + - * / and += -= *= /= 00250 // <li> <src>< <= == != >= ></src> 00251 // <li> sin 00252 // <li> cos 00253 // <li> tan 00254 // <li> asin 00255 // <li> acos 00256 // <li> atan 00257 // <li> atan2 00258 // <li> abs 00259 // <li> ceil 00260 // <li> floor 00261 // <li> <note role=caution> 00262 // It is assumed that all these functions return either Bool or 00263 // the same data type as inputted (i.e. QType). Special functions are 00264 // provided in this module to convert Int and LogicalArray to Bool; 00265 // and to convert were necessary to Complex (e.g. abs(Complex)). 00266 // </note> 00267 // </templating> 00268 00269 // <todo asof="941123"> 00270 // <li> Some inlining (did not work first go) 00271 // </todo> 00272 00273 template <class Qtype> class Quantum : public QBase{ 00274 //# Friends 00275 // Input, only quantity is supported now 00276 friend istream& operator>> (istream &is, Quantity &ku); 00277 public: 00278 //# Constructors 00279 // Default constructor, generates '0' 00280 Quantum(); 00281 // Copy constructor (deep copy) 00282 Quantum(const Quantum<Qtype> &other); 00283 // Construct undimensioned quantum (i.e. unit="") 00284 Quantum(const Qtype &factor); 00285 // Construct dimensioned quantum (e.g. '1.23 km/Mpc') 00286 // <thrown> 00287 // <li> AipsError if non-matching unit dimensions 00288 // </thrown> 00289 // <group> 00290 Quantum(const Qtype &factor, const Unit &s); 00291 // </group> 00292 // Construct quantum with unit copied from existing quantum 00293 Quantum(const Qtype &factor, const QBase &other); 00294 00295 // Destructor 00296 ~Quantum(); 00297 00298 //# Operators 00299 // Assignment (deep copy) 00300 Quantum<Qtype> &operator=(const Quantum<Qtype> &other); 00301 00302 00303 // Unary operations 00304 // <group> 00305 const Quantum<Qtype> &operator+() const; 00306 Quantum<Qtype> operator-() const; 00307 // </group> 00308 00309 // In place arithmetic functions: left hand side changed in place 00310 // <thrown> 00311 // <li> AipsError if non-conforming units (+ and -) 00312 // <li> AipsError if illegal result unit (* and /; programming error) 00313 // </thrown> 00314 // <group> 00315 Quantum<Qtype> &operator+=(const Quantum<Qtype> &other); 00316 Quantum<Qtype> &operator+=(const Qtype &other); 00317 Quantum<Qtype> &operator-=(const Quantum<Qtype> &other); 00318 Quantum<Qtype> &operator-=(const Qtype &other); 00319 Quantum<Qtype> &operator*=(const Quantum<Qtype> &other); 00320 Quantum<Qtype> &operator*=(const Qtype &other); 00321 Quantum<Qtype> &operator/=(const Quantum<Qtype> &other); 00322 Quantum<Qtype> &operator/=(const Qtype &other); 00323 // </group> 00324 00325 // Arithmetic operators: return Quantum<T> 00326 // <thrown> 00327 // <li> AipsError if non-conforming units (+ and -) 00328 // </thrown> 00329 // See <linkto group="QMath#Quantum mathematical operations">QMath</linkto> class for unequal argument types 00330 // <group> 00331 Quantum<Qtype> operator+(const Quantum<Qtype> &other) const; 00332 Quantum<Qtype> operator-(const Quantum<Qtype> &other) const; 00333 Quantum<Qtype> operator*(const Quantum<Qtype> &other) const; 00334 Quantum<Qtype> operator/(const Quantum<Qtype> &other) const; 00335 // </group> 00336 00337 //# General member functions 00338 // Get value of quantum in current units (i.e. in units specified in quantum) 00339 // <group> 00340 const Qtype &getValue() const; 00341 Qtype &getValue(); 00342 // </group> 00343 // Get value in canonical base units 00344 Qtype getBaseValue() const; 00345 // Get value in specified units 00346 Qtype getValue(const Unit &other) const; 00347 // Get the unit (as Unit) that is attached to the Quantum. (use getUnit() if 00348 // interested in the String part only, e.g. for output) 00349 virtual const Unit &getFullUnit() const; 00350 00351 // Re-specify parts of a quantum 00352 // <group name="set value"> 00353 // Scale ( i.e. multiply) the value of the Quantum without changing units 00354 void scale(const Qtype &factor); 00355 // Set the value without changing units 00356 void setValue(const Qtype &val); 00357 // Set the value and unit deduced from input string 00358 // <note role=caution> At the moment the implementation can only convert 00359 // scalars to the appropiate Quantum. If format for Array input defined, 00360 // it could easily be changed. In addition recognition of date/time/angle 00361 // still has to be added </note> 00362 // <group> 00363 static Bool read(Quantity &res, const String &in); 00364 static Bool read(Quantity &res, MUString &in); 00365 // </group> 00366 // </group> 00367 00368 // Check if of specified type 00369 Bool check(const UnitVal &uv) const; 00370 00371 // Assert correct kind 00372 // <thrown> 00373 // <li> AipsError if non-conforming unit dimensions 00374 // </thrown> 00375 void assure(const UnitVal &uv) const; 00376 00377 // Return a Quantum converted to specified units 00378 // <group name="get"> 00379 // Convert to canonical units 00380 Quantum<Qtype> get() const; 00381 // Convert to specified units; any remainder will be expressed in canonical 00382 // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s . 00383 // <thrown> 00384 // <li> AipsError if illegal unit 00385 // </thrown> 00386 Quantum<Qtype> get(const Unit &s) const; 00387 // Convert a Quantum to units from specified quantum (ibid example) 00388 Quantum<Qtype> get(const Quantum<Qtype> &other) const; 00389 // </group> 00390 00391 // Convert a Quantum to specified units 00392 // <group> 00393 // Convert to canonical units 00394 void convert(); 00395 // Convert to specified units; any remainder will be expressed in canonical 00396 // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s . 00397 // <thrown> 00398 // <li> AipsError if illegal unit 00399 // </thrown> 00400 void convert(const Unit &s); 00401 // Convert a Quantum to units from specified quantum (ibid example) 00402 void convert(const Quantum<Qtype> &other) ; 00403 // </group> 00404 // Get a copy of Quantum 00405 virtual QBase *clone() const; 00406 // Print a Quantum 00407 virtual void print(ostream &os) const; 00408 // Get the type (using QuantumType) of derived Quantum (faster than Strings) 00409 // <group> 00410 virtual uInt type() const; 00411 static uInt myType(); 00412 // </group> 00413 00414 private: 00415 //# Data members 00416 // Actual quantum value 00417 Qtype qVal; 00418 00419 }; 00420 00421 // Global functions 00422 // <summary> Global input function </summary> 00423 // Output/Input 00424 // <group name=output> 00425 // only Quantity is supported on input 00426 istream& operator>> (istream &is, Quantity &ku); 00427 Bool readQuantity(Quantity &res, MUString &in); 00428 Bool readQuantity(Quantity &res, const String &in); 00429 // </group> 00430 00431 00432 } //# NAMESPACE CASA - END 00433 00434 #ifndef CASACORE_NO_AUTO_TEMPLATES 00435 #include <casa/Quanta/Quantum.tcc> 00436 #endif //# CASACORE_NO_AUTO_TEMPLATES 00437 #endif