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