Quantum.h

Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1