casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Unit.h
Go to the documentation of this file.
00001 //# Unit.h: defines the Unit class
00002 //# Copyright (C) 1994-1996,1998-2000,2008
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: Unit.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00027 
00028 #ifndef CASA_UNIT_H
00029 #define CASA_UNIT_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/BasicSL/String.h>
00035 #include <casa/Quanta/UnitVal.h>
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 //# Forward Declarations
00040 
00041 // <summary>
00042 // defines physical units
00043 // </summary>
00044 
00045 // <use visibility=export>
00046 
00047 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tUnit">
00048 // </reviewed>
00049 //
00050 //# // <prerequisite>
00051 //# // </prerequisite>
00052 //
00053 //# // <etymology>
00054 //# // </etymology>
00055 //
00056 // <synopsis> 
00057 // Physical units are basically used as quantities (see the
00058 // <linkto class=Quantum>Quantum</linkto> class), i.e.
00059 // a value and a dimension. The Unit class, or one of its subsidaries,  will
00060 // in general not be called separately. The only reason to make use of these
00061 // classes is to generate additional 'tagged' units, i.e. units with a
00062 // special name, e.g. 'beam' for a telescope  beam, or 'JY', a non-SI name
00063 // for Jy.
00064 //  <h3> Units </h3>
00065 // A Unit is a String, and can be defined as either a Unit or a String
00066 // everywhere where a Unit is required.<br>
00067 // If defined as a Unit, the format of the string will be checked for a
00068 // legal definition and its value will be stored. If defined as a String,
00069 // the checking and determination of the value will be done each time
00070 // the string is encountered when a Unit is expected.<br>
00071 // <note role=tip> The use of a separate Unit variable will give a tremendous
00072 // speed increase, if compared to using the String representation in
00073 // e.g. <linkto class=Quantum>Quantity(5,"deg")</linkto> </note>
00074 // <note role=caution>
00075 // If using an explicit Unit variable (e.g. <src>Unit a("5Bolton/beam")</src>),
00076 // the check on the legality of the given string, and the conversion to the 
00077 // cached canonical value in the variable 'a', is only done at creation time. This
00078 // means that if the user changes the value of a unit involved by the 
00079 // <linkto class=UnitMap>putUser()</linkto> method, the unit using it should be
00080 // re-created (<src> a = Unit("5Bolton/beam");</src>).
00081 // </note>
00082 // A unit is a string of one or more fields separated 
00083 // by 'space' or '.' or '*' (FITS option)
00084 // (to indicate multiply) or '/' (to indicate divide).
00085 // Multiple separators are acted upon (i.e. m//s == m.s).
00086 // Separators are acted upon left-to-right (i.e. m/s/A == (m/s)/A; use
00087 // () to indicate otherwise (e.g. m/(s/A))).
00088 //
00089 // A field is a name, or a unit enclosed in (), optionally followed by an,
00090 // optionally signed, decimal constant.
00091 // The decimal constant may be proceeded by '**' or '^' (FITS option)
00092 //
00093 // E.g. m.(m/s)-2 == m-1.s2)
00094 // <note role=tip>
00095 // A 'space' or '.' before an opening '(' can be omitted.
00096 // </note>
00097 // A name can consist of case-sensitive letters, '_', ''', ':', '"' and '0'
00098 // ('0' not as first character). Digits 1-9 are allowed if preceded with
00099 // an '_'.
00100 //
00101 // Possible legal names are e.g. Jy, R0, R_1, "_2.
00102 // <note role=tip>
00103 // <ul>
00104 //   <li> ' is used for arcmin
00105 //   <li> '' or " for arcsec
00106 //   <li> : :: and ::: are used for h, min, s respectively
00107 //   <li> _ is used for an undimensioned value (like beam or pixel)
00108 // </ul>
00109 // </note>
00110 // <note role=caution> The standard naming conventions for SI units are that they are
00111 // all in lowercase, unless derived from a person's name, when they start
00112 // with a capital letter. Notable exceptions are some of the astronomical
00113 // SI related units (e.g. AU).
00114 // </note>
00115 // A name can be preceded by a (standard) decimal prefix.
00116 //
00117 // A name must be defined in a Unit map before it can be used.
00118 //
00119 // All SI units and some customary units are part of the classes. User
00120 // defined names can be added by the UnitMap::putUser() function (see
00121 // the <linkto class=UnitMap>UnitMap</linkto> class).
00122 //
00123 // Example:
00124 //      km/s/(Mpc.s)2  is identical to km.s-1.Mpc-2.s-2
00125 //
00126 // There are 5 name lists in the UnitMap, which are searched in reverse order:
00127 // <ol>
00128 //   <li> Defining units:       m, kg, s, A, K, cd, mol, rad, sr, _
00129 //   <li> SI units:             including a.o. g, Jy, AU
00130 //   <li> Customary units:      e.g. lb, hp, ly
00131 //   <li> User defined units:   defined by user (e.g. beam, KPH, KM)
00132 //   <li> Cached units: for speed in operations
00133 // </ol>
00134 // All known names can be viewed by running the tUnit test program, or
00135 // using the MapUnit::list() routine.
00136 // They are also (at least the 1999/09/15 values) available in the
00137 // <linkto module="Quanta">Quanta module documentation</linkto>.
00138 // <note role=caution>
00139 // There is a difference between units without a dimension (non-dimensioned
00140 // I will call them), and undimensioned units. Non-dimensioned examples are
00141 // "", "%"; undimensioned examples: "beam", "pixel".
00142 // </note>
00143 //
00144 //  <h3> Unit class </h3>
00145 // The Unit class is not directly based on the String class, but Strings and 
00146 // Units are interchangeable in all Unit and Quantum related calls.
00147 // (But notice the earlier note on speed if using explicit Strings often.)
00148 //
00149 // To calculate with Units (or Strings representing units), use the
00150 // <linkto class=UnitVal>UnitVal</linkto> class. To use dimensioned values,
00151 // use the <linkto class=Quantum>Quantum</linkto> (cq Quantity) class.
00152 //
00153 // Using Unit i.s.o. String will give an immediate check of the legality
00154 // of the unit string.
00155 // In addition the UnitVal class contains a check facility to determine the
00156 // legality of a unit string:
00157 // <srcblock>
00158 // Bool UnitVal::check("string");
00159 // </srcblock>
00160 // 
00161 // </synopsis> 
00162 //
00163 // <example>
00164 // <srcblock>
00165 // #include <casa/Quanta.h>
00166 // // check if a string is a valid unit
00167 // if ( !UnitVal::check("Km") ) { cout << "Invalid unit string " << "Km" << endl;
00168 // // define some units
00169 // String unit1="km/Mpc";
00170 // Unit unit2="uJy/Mpc";
00171 // // define your own unit name
00172 // UnitMap::putUser("my_univ", UnitVal( C::pi, unit2), "My universe param");
00173 // // use the units in model calculations
00174 // Quantity observed( 8.97, "Mmy_univ/a");
00175 // Quantity theory (3.8e-9, "mmy_univ/s");
00176 // if ( ( observed / theory) < 1.) { cout << "Eureka" << endl;
00177 // </srcblock>
00178 // </example>
00179 //
00180 // <motivation>
00181 // Make basis for all dimensioned values the SI system of units
00182 // </motivation>
00183 //
00184 // <todo asof="941110">
00185 //   <li> Some inlining (did not work first go)
00186 //   <li> Look into possiblity of conversion routine from rad2 to sr
00187 // </todo>
00188 
00189 class Unit {
00190     public:
00191 //# Constructors
00192 // Default empty string constructor
00193     Unit();
00194 // Copy constructor
00195     Unit(const Unit &other);
00196 // String based constructors.
00197 // <thrown>
00198 //   <li> AipsError if illegal unit string
00199 // </thrown>
00200 // <group name="constructor">
00201     Unit(const String &other);
00202     Unit(const Char *other);
00203     explicit Unit(Char other);
00204     Unit(const Char *other, Int len);
00205 // </group>
00206 // Destructor
00207     ~Unit();
00208 
00209 //* Operators
00210 // Copy assignment
00211     Unit& operator=(const Unit &other);
00212 // Comparisons. Comparisons are done on the basis of the inherent units. I.e.
00213 // <src>m/s</src> are identical to <src>AU/cy</src>.
00214 // <group>
00215     Bool operator==(const Unit &other) const;
00216     Bool operator!=(const Unit &other) const;
00217 // Fast check for "" units
00218     Bool empty() const;
00219 // </group>
00220 //# Member functions
00221 // Get the unit value
00222     const UnitVal &getValue() const;
00223 // Get the unit name
00224     const String &getName() const;
00225 // Set the unit value
00226     void setValue(const UnitVal &in);
00227 // Set the unit name
00228     void setName(const String &in);
00229 
00230 private:
00231 //# Data
00232     String uName;
00233     UnitVal uVal;
00234 
00235 //# Member functions
00236 // Check format of unit string
00237 // <thrown>
00238 //   <li> AipsError
00239 // </thrown>
00240     void check();
00241 };
00242 
00243 //# Inline Implementations
00244 
00245 
00246 } //# NAMESPACE CASA - END
00247 
00248 #endif