casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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 
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