casa
$Rev:20696$
|
00001 //# UnitVal.h: defines the class describing a unit as a value and a dimension 00002 //# Copyright (C) 1994-1999,2000,2001,2004 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: UnitVal.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00027 00028 #ifndef CASA_UNITVAL_H 00029 #define CASA_UNITVAL_H 00030 00031 00032 //# Includes 00033 #include <casa/aips.h> 00034 #include <casa/Quanta/UnitDim.h> 00035 #include <casa/iosfwd.h> 00036 00037 namespace casa { //# NAMESPACE CASA - BEGIN 00038 00039 //# Forward Declarations 00040 class String; 00041 class MUString; 00042 class UnitMap; 00043 00044 // 00045 // <summary> 00046 // describes any valid unit as a factor and a dimenion of SI units 00047 // </summary> 00048 00049 // <use visibility=export> 00050 00051 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tUnit"> 00052 // 00053 // <prerequisite> 00054 // You should have at least a preliminary understanding of these classes: 00055 // <li> <linkto class=Unit>Unit</linkto> 00056 // </prerequisite> 00057 // 00058 // <etymology> 00059 // The class name derives from Units and gives a Value for a unit string 00060 // </etymology> 00061 // 00062 // <synopsis> 00063 // Physical units are strings consisting of one or more names of known 00064 // basic units, separated by '.' or ' ' (for multiplication) or '/' (for 00065 // division). Each name can optionally be preceded by a standard decimal 00066 // prefix, and/or followed by an (optionally signed) exponent. 00067 // Example: 00068 // km/s/(Mpc.s)2 is identical to km.s-1.Mpc-2.s-2 00069 // 00070 // See the <linkto class="Unit">Unit</linkto> class for more details. 00071 // 00072 // The UnitVal class maps a Unit string to a factor and a dimension of SI 00073 // defining units. E.g 'km/s' will be 1000 m.s-1 . 00074 // This class is only of interest if the manipulation of units is of 00075 // direct interest. Normally units will be used as Quantities and Quantums 00076 // (see the <linkto class=Quantum>Quantum</linkto> class) only, 00077 // i.e. as a physical quantity having a value and unit. 00078 // The class can also be used to check the validity of a unit string. 00079 // 00080 // <h3> Constructing UnitVal values </h3> 00081 // 00082 // UnitVal has the following constructors: 00083 // <ul> 00084 // <li> UnitVal() creates an (non-dimensioned) value 1. 00085 // <li> UnitVal(Double f) creates an (non-dimensioned) value f. 00086 // <li> UnitVal(Double f, String s) creates value f with unit s 00087 // <li> UnitVal(Double f, Int i) (private) creates value f with unit 00088 // at position i in dimension vector 00089 // </ul> 00090 // 00091 // 00092 // <h3> Manipulating unit values </h3> 00093 // 00094 // The UnitVal can be manipulated by the following operators and functions: 00095 // <ul> 00096 // <li> *, / generates combined UnitVal (e.g. 1 yd * 1 m = 0.9 m2) 00097 // <li> pow(Int) UnitVal(2,"km")->pow(2) = 4000000 m2 00098 // <li> root(Int) UnitVal(4000000,"m2")->root(2) = 2 km 00099 // <li> ==, != compares dimensions only: 1 yd == 5 ly: True 00100 // <li> getFac() will return the factor (Double) 00101 // <li> getDim() will return the dimensions (as UnitDim) 00102 // <li> << will output formatted unit (factor and dimension) 00103 // </ul> 00104 // To aid in checking the dimensionality of units, the following constants 00105 // are available: 00106 // <ul> 00107 // <li> UnitVal::NODIM 00108 // <li> UnitVal::UNDIM 00109 // <li> UnitVal::LENGTH 00110 // <li> UnitVal::MASS 00111 // <li> UnitVal::ANGLE 00112 // <li> UnitVal::SOLIDANGLE 00113 // <li> UnitVal::MOLAR 00114 // <li> UnitVal::CURRENT 00115 // <li> UnitVal::TIME 00116 // <li> UnitVal::TEMPERATURE 00117 // <li> UnitVal::INTENSITY 00118 // </ul> 00119 // <note role=tip> 00120 // Any other dimension can be checked by a combination. To check e.g. if 00121 // a unit is an acceleration, use: UnitVal::LENGTH/UnitVal::TIME/UnitVal::TIME 00122 // </note> 00123 // 00124 // <h3> Checking for valid unit strings </h3> 00125 // 00126 // The validity of a unit string can be checked by: 00127 // <srcblock> 00128 // // Check if the given String is a valid unit representation. The String 00129 // // will be cached in the unit maps for later reference if True 00130 // if ( UnitVal::check( "km/s/Mpc") ) {...} 00131 // </srcblock> 00132 // 00133 // </synopsis> 00134 // 00135 // <example> 00136 // An observation contains values in Janskys and in Westerbork Units. The 00137 // data can be combined by the following code: 00138 // <srcblock> 00139 // // The Fits tape gave JY, we check if defined, else we define them 00140 // if ( !UnitVal::check( "JY")) { 00141 // UnitMap::putUser("JY", UnitVal(1.,"Jy"), "FITS way to write Jy"); 00142 // } 00143 // // The Fits tape gave WU (which are defined): 00144 // // We check if JY and WU are of the same dimension: 00145 // if (UnitVal(1.,"JY") != UnitVal(1.,"WU")) { 00146 // cerr << "Wrong dimension for either JY ( " << 00147 // UnitVal(1.,"JY")->getDim() << 00148 // ") or WU ( " << 00149 // UnitVal(1.,"WU")->getDim() << ")" << endl; 00150 // } 00151 // // And output the relation between WU and JY, and the WU value: 00152 // cout << "1 WU = " << ( UnitVal(1.,"WU")/UnitVal(1.,"Jy") )->getVal() << 00153 // " JY with 1 WU = " << UnitVal(1.,"WU") << endl; 00154 // </srcblock> 00155 // </example> 00156 00157 // <motivation> 00158 // To separate the actual manipulation of unit values from the related 00159 // quantity 00160 // </motivation> 00161 // 00162 // <todo asof="941110"> 00163 // <li> Some inlining (did not work first go) 00164 // </todo> 00165 00166 class UnitVal { 00167 //# Friends 00168 // Multiply 00169 friend UnitVal operator*(const UnitVal &in, const UnitVal &other); 00170 // Divide 00171 friend UnitVal operator/(const UnitVal &in, const UnitVal &other); 00172 // Output a unit as a value and a string of SI defining units 00173 friend ostream& operator<<(ostream &os, const UnitVal &ku); 00174 // ensure that statics are initialized 00175 friend class UnitVal_static_initializer; 00176 00177 public: 00178 //# Constructors 00179 // Construct an non-dimensioned value of 1 00180 UnitVal(); 00181 // Copy constructor 00182 UnitVal(const UnitVal &other); 00183 00184 // Construct an non-dimensioned value 00185 UnitVal(Double factor) { init(factor); } 00186 00187 // Construct a fully dimensioned value 00188 // <thrown> 00189 // <li> AipsError 00190 // </thrown> 00191 UnitVal(Double factor, const String &s); 00192 00193 // Construct a value with a single unit at position specified 00194 UnitVal(Double factor, Int pos) { init(factor, pos); } 00195 00196 // Destructor 00197 ~UnitVal(); 00198 00199 //# Operators 00200 // Assignment (copy semantics) 00201 UnitVal &operator=(const UnitVal &other); 00202 00203 // Manipulate units 00204 // <group name="manipulate"> 00205 // Multiply different units 00206 UnitVal &operator*=(const UnitVal &other); 00207 00208 // Divide different units 00209 UnitVal &operator/=(const UnitVal &other); 00210 00211 // Compare the dimensionality of different units 00212 Bool operator==(const UnitVal &other) const; 00213 Bool operator!=(const UnitVal &other) const; 00214 // </group> 00215 00216 //# General member functions 00217 00218 // Raise a unit to an integer power 00219 UnitVal pow(Int p); 00220 00221 // Take integer root 00222 // <thrown> 00223 // <li> AipsError if power equals zero 00224 // <li> AipsError if unit dimensions not multiple of power 00225 // </thrown> 00226 // <group> 00227 UnitVal root(Int p) const; 00228 UnitVal sqrt() const; 00229 // </group> 00230 00231 // Get the data parts of the unit value definition 00232 // <group name="get data"> 00233 // Get the dimensions in the defining SI units 00234 const UnitDim &getDim() const; 00235 00236 // Get the factor of the unit (as compared to pure SI units) 00237 Double getFac() const; 00238 // </group> 00239 00240 //# Helper functions 00241 // Convert a unit string to a proper unit value and cache the result. The 00242 // function will return False if invalid string specified 00243 static Bool check(const String &s); 00244 00245 // Convert a unit string to a proper unit value, cache the result and compare 00246 // the dimension with the specified unit value. False if any of the steps fails 00247 static Bool check(const String &s, UnitVal &loc); 00248 00249 00250 //# Data members 00251 // Some constants to check type of units 00252 // <group name="unit kinds"> 00253 static UnitVal NODIM; 00254 static UnitVal UNDIM; 00255 static UnitVal LENGTH; 00256 static UnitVal MASS; 00257 static UnitVal TIME; 00258 static UnitVal CURRENT; 00259 static UnitVal TEMPERATURE; 00260 static UnitVal INTENSITY; 00261 static UnitVal MOLAR; 00262 static UnitVal ANGLE; 00263 static UnitVal SOLIDANGLE; 00264 // </group> 00265 00266 protected: 00267 // alternate initialization 00268 void init(Double factor); 00269 void init(Double factor, Int pos); 00270 00271 private: 00272 //# Data members 00273 // The factor necessary to express the specified unit in the defining SI units 00274 Double kindFactor; 00275 00276 // The dimensions of the unit in the defining SI units 00277 UnitDim kindDim; 00278 00279 // Convert (and check) a unit string to an SI value representation 00280 // <group> 00281 static Bool create(const String &s, UnitVal &res); 00282 static Bool create(MUString &str, UnitVal &res); 00283 // </group> 00284 00285 // Determine sign of unit power (i.e. if '.' or '/') 00286 static Int psign(MUString &str); 00287 00288 // Determine exponent of unit symbol 00289 static Int power(MUString &str); 00290 00291 // Determine symbol name in unit string 00292 static Bool field(MUString &str, UnitVal &res); 00293 00294 }; 00295 00296 //# Inline Implementations 00297 00298 //# Global functions 00299 // <summary> Global output function </summary> 00300 // <group name=output> 00301 // Output 00302 ostream& operator<<(ostream &os, const UnitVal &ku); 00303 // </group> 00304 00305 // <summary> Static initialisation of UnitVal constants </summary> 00306 static class UnitVal_static_initializer { 00307 public: 00308 UnitVal_static_initializer( ) { 00309 if ( ! initialized ) { 00310 UnitVal::NODIM.init( 1.); 00311 UnitVal::UNDIM.init( 1., UnitDim::Dnon); 00312 UnitVal::LENGTH.init( 1., UnitDim::Dm); 00313 UnitVal::MASS.init( 1., UnitDim::Dkg); 00314 UnitVal::TIME.init( 1., UnitDim::Ds); 00315 UnitVal::CURRENT.init( 1., UnitDim::DA); 00316 UnitVal::TEMPERATURE.init( 1., UnitDim::DK); 00317 UnitVal::INTENSITY.init( 1., UnitDim::Dcd); 00318 UnitVal::MOLAR.init( 1., UnitDim::Dmol); 00319 UnitVal::ANGLE.init( 1., UnitDim::Drad); 00320 UnitVal::SOLIDANGLE.init( 1., UnitDim::Dsr); 00321 initialized = 1; 00322 } 00323 } 00324 private: 00325 static int initialized; 00326 } unitval_static_initializer; 00327 00328 00329 } //# NAMESPACE CASA - END 00330 00331 #endif 00332