//# Quantum.h: class to manipulate physical, dimensioned quantities //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: Quantum.h 20993 2010-11-08 13:36:32Z gervandiepen $ #ifndef CASA_QUANTUM_H #define CASA_QUANTUM_H #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN //# Forward Declarations template class Quantum; //# Typedefs typedef Quantum Quantity; // // Quantities (i.e. dimensioned values) // // // // // // //
  • Unit // // // // A Quantity is defined as a single Double value with attached units. // From this definition the templated Quantum class arose, to have non-Double, // non-scalar quantities. // // // // Quantities are values with a unit. Their basic specification can be one of // two forms: // // Quantity( Double value, String unit); // or: Unit unit // Quantum ( Type value, String unit) // or: Unit unit // // // A unit is a string of known unit fields separated // by 'space' or '.' (to indicate multiply) or '/' (to indicate divide). // See the Unit class for details. // // Example: km/s/(Mpc.s)2 is identical to km.s-1.Mpc-2.s-2 // //

    Defining a Quantum

    // The following list of constructors is available. // // In the following 'String' can be replaced by 'Unit' everywhere. The // only difference being a check for a legitimate unit string being executed // if Unit specified (with exception if error) // // // 'Quantum' can, if Type equals Double, be replaced // with 'Quantity' // // 'Type' can be any simple or non-simple arithmetic type. // // E.g. , , > // //
      //
    • Quantum() value 0 generated //
    • Quantum( Quantum) copy constructor //
    • Quantum( Type factor) value factor generated //
    • Quantum( Type factor, Unit unit) specified quantity //
    • Quantum( Type factor, Quantum quant) specified factor, // the unit from the quant //
    // // //

    Manipulating quantities

    // Mathematical operators and functions and // logical operations (comparisons) // are defined on Quantums. They are, // of course, only available if the template Type supports them. //
      //
    • = assignment of identical //
    • * *= multiple two Quantums of same , or Quantum and type //
    • / /= divide two Quantums of same , or Quantum and type // note: // In multiplication and division, and if is scalar, the left or // right-hand side can be of type (e.g 2.*Quantity is allowed) //
    • + += add two Quantums of same or Quantum and type // and same unit dimensions (else exception) //
    • - -= subtract (same as +) //
    • - negate Quantum //
    • + unary + on Quantum //
    • == != compare unit dimensions and value of same . They will // be unequal if the units do not match or the values (possibly // converted to common base units). All comparisons work also // on a Quantum and //
    • < > compare unit dimensions. Exception if no match, // else compare the values //
    • <= >= ibid //
    • pow(Int) raise to an (integer) power //
    // // //

    Manipulating the value and/or units of quanta

    // Quantities can be converted to other units by the following set of member // functions: //
      //
    • convert() will convert the quantum to canonical units. // E.g. given myval=Quantity(5.,"Jy"), // myval.convert() will convert the qunatum to // Quantity(5.e-26,"kg.s-2") //
    • convert(Unit unit) will convert the quantum to the // specified unit with any remaining dimensions // expressed in canonical units. E.g given // myval as above, myval.convert("W/cm") will // make it Quantity(5.e-28,"W/cm.m-1.s") //
    • convert(Quantum quant) will convert the quantum // to the units of the specified quant with the // same conversion rules as the previous one //
    // All converting type methods (i.e. convert(), get() and // getValue() with specified units), will automatically convert also from // time to angle units (or v.v) if necessary, as long as they are simple. I.e. // deg will be converted to h, but asking to convert m/s to m/deg will // produce the standard conversion to m/deg.rad/s. // // Quanta can be checked for having the correct unit dimensions (e.g. before // addition or comparing) by the following two member functions, which will // return a Bool value: //
      //
    • isConform(Unit unit) //
    • isConform(Quantum quant) //
    • check(UnitVal kind) //
    // or by an assertion, which will throw an exception:
    //
      //
    • assure(UnitVal kind) //
    // // The quantum can be retrieved with a change in units by: //
      //
    • get() will return the quantum converted to canonical units. // E.g. given myval=Quantity(5.,"Jy"), // myval.get() will return // Quantity(5.e-26,"kg.s-2") //
    • get(Unit unit) will return the quantum converted to the // specified unit with any remaining dimensions // expressed in canonical units. E.g given // myval as above, myval.get("W/cm") will // return it as Quantity(5.e-28,"W/cm.m-1.s") //
    • get(Quantum quant) will return the quantum converted // to the units of the specified quant with the // same conversion rules as the previous one //
    // // The value and units of a quantum can be set or retrieved separately by the // following member functions: //
      //
    • getValue() return the value (as Type) of the quantum. // myval.get().getValue() will return the // value of myval expressed in canonical units // //
    • getValue(Unit unit) return the value (as converted to unit) //
    • getUnit() return the String part of the unit of the // quantum (use getFullUnit if interested in // the complete Unit, e.g. for re-use) //
    • getFullUnit() return the complete unit of the Quantum (use // getUnit() if interested in String part only) //
    • setValue(Type val) replace the value of the quantum with val, // leaving the units the same //
    • scale(Type val) multiply the value (leaving units same) by the // specified value //
    • setUnit(Unit unit) replace the units of the quantum, leaving // the value the same. //
    • setUnit(Quantum quant) ibid //
    • set(String quantity) replace the value and unit as deduced from quantity //
    // // The output operator (<<) will produce the value of the quantum and its // units. Given Quantity myval(5.,"mJy"), << myval will produce: // 5.0 mJy; while << myval.get("yW/m2") // will produce: .00005 yW/m2.s.
    // The input operator (>>, or the static read functions) will // convert a String to a Quantum (quantity only for now). The analysis // will do the following: //
      //
    • Check if it can be converted as a time/angle, if so use // (MVAngle) //
    • Check if it can be used as a date/time. if so use // (MVTime) //
    • Interpret as a value with units //
    // Since e.g. 12d could be interpreted as // being both an angle (12 degrees) or a quantity (12 days), the only way // is to differentiate them with a decimal point (12.d will be days) // //
    // // // An experiment has measured the energy of a photon in keV. The following will // output the wavelength and frequency of this photon (see the // QC class for quantity constants): // // #include // Double myval; // keV photon energy // Quantity quant(myval,"keV"); // make quantity // cout << "A photon with energy " << quant << endl // << " has a frequency of " // << (quant/QC::h)->get("GHz") << endl // h=Planck // << " and a wavelength of " // << (QC::c/quant/QC::h)->get("nm") // c=light velocity // << " or " << QC::c/quant/QC::h << endl; // // // // // Major use is foreseen in all calculations with observed data. // // //
  • prefix +,- //
  • + - * / and += -= *= /= //
  • < <= == != >= > //
  • sin //
  • cos //
  • tan //
  • asin //
  • acos //
  • atan //
  • atan2 //
  • abs //
  • ceil //
  • floor //
  • // It is assumed that all these functions return either Bool or // the same data type as inputted (i.e. QType). Special functions are // provided in this module to convert Int and LogicalArray to Bool; // and to convert were necessary to Complex (e.g. abs(Complex)). // // // //
  • Some inlining (did not work first go) // template class Quantum : public QBase{ //# Friends // Input, only quantity is supported now friend istream& operator>> (istream &is, Quantity &ku); public: //# Constructors // Default constructor, generates '0' Quantum(); // Copy constructor (deep copy) Quantum(const Quantum &other); // Construct undimensioned quantum (i.e. unit="") Quantum(const Qtype &factor); // Construct dimensioned quantum (e.g. '1.23 km/Mpc') // //
  • AipsError if non-matching unit dimensions // // Quantum(const Qtype &factor, const Unit &s); // // Construct quantum with unit copied from existing quantum Quantum(const Qtype &factor, const QBase &other); //# Operators // Assignment (deep copy) Quantum &operator=(const Quantum &other); // Unary operations // const Quantum &operator+() const; Quantum operator-() const; // // In place arithmetic functions: left hand side changed in place // //
  • AipsError if non-conforming units (+ and -) //
  • AipsError if illegal result unit (* and /; programming error) // // Quantum &operator+=(const Quantum &other); Quantum &operator+=(const Qtype &other); Quantum &operator-=(const Quantum &other); Quantum &operator-=(const Qtype &other); Quantum &operator*=(const Quantum &other); Quantum &operator*=(const Qtype &other); Quantum &operator/=(const Quantum &other); Quantum &operator/=(const Qtype &other); // // Arithmetic operators: return Quantum // //
  • AipsError if non-conforming units (+ and -) // // See QMath class for unequal argument types // Quantum operator+(const Quantum &other) const; Quantum operator-(const Quantum &other) const; Quantum operator*(const Quantum &other) const; Quantum operator/(const Quantum &other) const; // //# General member functions // Get value of quantum in current units (i.e. in units specified in quantum) // const Qtype &getValue() const; Qtype &getValue(); // // Get value in canonical base units Qtype getBaseValue() const; // Get value in specified units. // If the other units do not conform to the units of this // object and requireConform is True, an exception is thrown, // with the following exceptions: //
    - angle to/from time conversions are implicitly supported //
    - frequency to/from/ wavelength conversions are implicitly supported //#
    Note, I added requireConform and made the default value False for //# backward compatibility. However, I think that ultimately requireConform //# should be removed and an exception should be thrown if the units do //# not conform. It's not clear to me why this was not in the original //# implementation; it's much too easy for non-conformation bugs to //# slip by unnoticed. - dmehring 09feb2015 //# It should be left in since conversion from time to angle makes sense. //# Maybe the default could be changed to True. - gvandiepen09feb2016 Qtype getValue(const Unit &other, Bool requireConform=False) const; // Get the unit (as Unit) that is attached to the Quantum. (use getUnit() if // interested in the String part only, e.g. for output) virtual const Unit &getFullUnit() const; // Re-specify parts of a quantum // // Scale ( i.e. multiply) the value of the Quantum without changing units void scale(const Qtype &factor); // Set the value without changing units void setValue(const Qtype &val); // Set the value and unit deduced from input string // At the moment the implementation can only convert // scalars to the appropiate Quantum. If format for Array input defined, // it could easily be changed. In addition recognition of date/time/angle // still has to be added // static Bool read(Quantity &res, const String &in); static Bool read(Quantity &res, MUString &in); // // // Check if of specified type Bool check(const UnitVal &uv) const; // Assert correct kind // //
  • AipsError if non-conforming unit dimensions // void assure(const UnitVal &uv) const; // Return a Quantum converted to specified units // // Convert to canonical units Quantum get() const; // Convert to specified units; any remainder will be expressed in canonical // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s . // //
  • AipsError if illegal unit // Quantum get(const Unit &s) const; // Convert a Quantum to units from specified quantum (ibid example) Quantum get(const Quantum &other) const; // // Convert a Quantum to specified units // // Convert to canonical units void convert(); // Convert to specified units; any remainder will be expressed in canonical // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s . // //
  • AipsError if illegal unit // void convert(const Unit &s); // Convert a Quantum to units from specified quantum (ibid example) void convert(const Quantum &other) ; // // Get a copy of Quantum virtual QBase *clone() const; // Print a Quantum virtual void print(ostream &os) const; // Get the type (using QuantumType) of derived Quantum (faster than Strings) // virtual uInt type() const; static uInt myType(); // private: //# Data members // Actual quantum value Qtype qVal; }; // Global functions // Global input function // Output/Input // // only Quantity is supported on input istream& operator>> (istream &is, Quantity &ku); Bool readQuantity(Quantity &res, MUString &in); Bool readQuantity(Quantity &res, const String &in); // //# Declare extern templates for often used types. extern template class Quantum; } //# NAMESPACE CASACORE - END #ifndef CASACORE_NO_AUTO_TEMPLATES #include #endif //# CASACORE_NO_AUTO_TEMPLATES #endif