casacore
Loading...
Searching...
No Matches
Quantum.h
Go to the documentation of this file.
1// # Quantum.h: class to manipulate physical, dimensioned quantities
2// # Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001
3// # Associated Universities, Inc. Washington DC, USA.
4// #
5// # This library is free software; you can redistribute it and/or modify it
6// # under the terms of the GNU Library General Public License as published by
7// # the Free Software Foundation; either version 2 of the License, or (at your
8// # option) any later version.
9// #
10// # This library is distributed in the hope that it will be useful, but WITHOUT
11// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13// # License for more details.
14// #
15// # You should have received a copy of the GNU Library General Public License
16// # along with this library; if not, write to the Free Software Foundation,
17// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18// #
19// # Correspondence concerning AIPS++ should be addressed as follows:
20// # Internet email: casa-feedback@nrao.edu.
21// # Postal address: AIPS++ Project Office
22// # National Radio Astronomy Observatory
23// # 520 Edgemont Road
24// # Charlottesville, VA 22903-2475 USA
25
26#ifndef CASA_QUANTUM_H
27#define CASA_QUANTUM_H
28
29#include <casacore/casa/aips.h>
30#include <casacore/casa/Quanta/QBase.h>
31#include <casacore/casa/iosstrfwd.h>
32
33namespace casacore { // # NAMESPACE CASACORE - BEGIN
34
35// # Forward Declarations
36template <class T>
37class Quantum;
38
39// # Typedefs
41
42// <summary>
43// Quantities (i.e. dimensioned values)
44// </summary>
45
46// <use visibility=export>
47
48// <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tQuantum">
49// </reviewed>
50//
51// <prerequisite>
52// <li> <linkto class=Unit>Unit</linkto>
53// </prerequisite>
54//
55// <etymology>
56// A Quantity is defined as a single Double value with attached units.
57// From this definition the templated Quantum class arose, to have non-Double,
58// non-scalar quantities.
59// </etymology>
60//
61// <synopsis>
62// Quantities are values with a unit. Their basic specification can be one of
63// two forms:
64// <srcblock>
65// Quantity( Double value, String unit); // or: Unit unit
66// Quantum<Type> ( Type value, String unit) // or: Unit unit
67// </srcblock>
68//
69// A unit is a string of known unit fields separated
70// by 'space' or '.' (to indicate multiply) or '/' (to indicate divide).
71// See the <linkto class=Unit>Unit</linkto> class for details.
72//
73// Example: km/s/(Mpc.s)2 is identical to km.s-1.Mpc-2.s-2
74//
75// <h3> Defining a Quantum </h3>
76// The following list of constructors is available.
77// <note role=tip>
78// In the following 'String' can be replaced by 'Unit' everywhere. The
79// only difference being a check for a legitimate unit string being executed
80// if Unit specified (with exception if error)
81// </note>
82// <note role=tip>
83// <src>'Quantum<Type>'</src> can, if Type equals Double, be replaced
84// with 'Quantity'
85//
86// 'Type' can be any simple or non-simple arithmetic type.
87//
88// E.g. <src><Double>, <Complex>, <Vector<Double> ></src>
89// </note>
90// <ul>
91// <li> <src>Quantum<Type>() value 0 generated</src>
92// <li> <src>Quantum<Type>( Quantum<Type>) copy constructor</src>
93// <li> <src>Quantum<Type>( Type factor) value factor generated</src>
94// <li> <src>Quantum<Type>( Type factor, Unit unit) specified quantity</src>
95// <li> <src>Quantum<Type>( Type factor, Quantum<any> quant) specified factor,</src>
96// the unit from the quant
97// </ul>
98//
99//
100// <h3> Manipulating quantities </h3>
101// <linkto group="QMath.h#Quantum mathematical operations">Mathematical operators and
102// functions</linkto> and
103// <linkto group="QLogical.h#Quantum logical operations">logical operations</linkto> (comparisons)
104// are defined on Quantums. They are,
105// of course, only available if the template Type supports them.
106// <ul>
107// <li> <src>= assignment of identical <type></src>
108// <li> <src>* *= multiple two Quantums of same <type>, or Quantum and type</src>
109// <li> <src>/ /= divide two Quantums of same <type>, or Quantum and type</src>
110// note:
111// In multiplication and division, and if <src><type></src> is scalar, the left or
112// right-hand side can be of type <src><type></src> (e.g 2.*Quantity is allowed)
113// <li> <src>+ += add two Quantums of same <type> or Quantum and type</src>
114// and same unit dimensions (else exception)
115// <li> - -= subtract (same as +)
116// <li> - negate Quantum
117// <li> + unary + on Quantum
118// <li> <src>== != compare unit dimensions and value of same <type>. They will</src>
119// be unequal if the units do not match or the values (possibly
120// converted to common base units). All comparisons work also
121// on a <src>Quantum<type> and <type></src>
122// <li> <src>< > compare unit dimensions. Exception if no match,</src>
123// else compare the values
124// <li> <src><= >= ibid</src>
125// <li> pow(Int) raise to an (integer) power
126// </ul>
127//
128//
129// <h3> Manipulating the value and/or units of quanta </h3>
130// Quantities can be converted to other units by the following set of member
131// functions:
132// <ul>
133// <li> convert() will convert the quantum to canonical units.
134// E.g. given myval=Quantity(5.,"Jy"),
135// myval.convert() will convert the qunatum to
136// Quantity(5.e-26,"kg.s-2")
137// <li> convert(Unit unit) will convert the quantum to the
138// specified unit with any remaining dimensions
139// expressed in canonical units. E.g given
140// myval as above, myval.convert("W/cm") will
141// make it Quantity(5.e-28,"W/cm.m-1.s")
142// <li> <src>convert(Quantum<Type> quant) will convert the quantum</src>
143// to the units of the specified quant with the
144// same conversion rules as the previous one
145// </ul>
146// <note role=tip> All converting type methods (i.e. convert(), get() and
147// getValue() with specified units), will automatically convert also from
148// time to angle units (or v.v) if necessary, as long as they are simple. I.e.
149// deg will be converted to h, but asking to convert m/s to m/deg will
150// produce the standard conversion to m/deg.rad/s. </note>
151//
152// Quanta can be checked for having the correct unit dimensions (e.g. before
153// addition or comparing) by the following two member functions, which will
154// return a Bool value:
155// <ul>
156// <li> isConform(Unit unit)
157// <li> <src>isConform(Quantum<Type> quant)</src>
158// <li> check(UnitVal kind)
159// </ul>
160// or by an assertion, which will throw an exception:<br>
161// <ul>
162// <li> assure(UnitVal kind)
163// </ul>
164//
165// The quantum can be retrieved with a change in units by:
166// <ul>
167// <li> get() will return the quantum converted to canonical units.
168// E.g. given myval=Quantity(5.,"Jy"),
169// myval.get() will return
170// Quantity(5.e-26,"kg.s-2")
171// <li> get(Unit unit) will return the quantum converted to the
172// specified unit with any remaining dimensions
173// expressed in canonical units. E.g given
174// myval as above, myval.get("W/cm") will
175// return it as Quantity(5.e-28,"W/cm.m-1.s")
176// <li> <src>get(Quantum<Type> quant) will return the quantum converted</src>
177// to the units of the specified quant with the
178// same conversion rules as the previous one
179// </ul>
180//
181// The value and units of a quantum can be set or retrieved separately by the
182// following member functions:
183// <ul>
184// <li> getValue() return the value (as Type) of the quantum.
185// <note role=tip> myval.get().getValue() will return the
186// value of myval expressed in canonical units
187// </note>
188// <li> getValue(Unit unit) return the value (as converted to unit)
189// <li> getUnit() return the String part of the unit of the
190// quantum (use getFullUnit if interested in
191// the complete Unit, e.g. for re-use)
192// <li> getFullUnit() return the complete unit of the Quantum (use
193// getUnit() if interested in String part only)
194// <li> setValue(Type val) replace the value of the quantum with val,
195// leaving the units the same
196// <li> scale(Type val) multiply the value (leaving units same) by the
197// specified value
198// <li> setUnit(Unit unit) replace the units of the quantum, leaving
199// the value the same.
200// <li> <src>setUnit(Quantum<Type> quant) ibid</src>
201// <li> set(String quantity) replace the value and unit as deduced from quantity
202// </ul>
203//
204// The output operator (<src><<</src>) will produce the value of the quantum and its
205// units. Given <src>Quantity myval(5.,"mJy"), << myval</src> will produce:
206// <src>5.0 mJy</src>; while <src><< myval.get("yW/m2")</src>
207// will produce: <src>.00005 yW/m2.s</src>.<br>
208// The input operator (<src>>></src>, or the static read functions) will
209// convert a String to a Quantum (quantity only for now). The analysis
210// will do the following:
211// <ul>
212// <li> Check if it can be converted as a time/angle, if so use
213// (<linkto class=MVAngle>MVAngle</linkto>)
214// <li> Check if it can be used as a date/time. if so use
215// (<linkto class=MVTime>MVTime</linkto>)
216// <li> Interpret as a value with units
217// </ul>
218// <note role=caution> Since e.g. <em>12d</em> could be interpreted as
219// being both an angle (12 degrees) or a quantity (12 days), the only way
220// is to differentiate them with a decimal point (12.d will be days)</note>
221//
222// </synopsis>
223//
224// <example>
225// An experiment has measured the energy of a photon in keV. The following will
226// output the wavelength and frequency of this photon (see the
227// <linkto class=QC">QC</linkto> class for quantity constants):
228// <srcblock>
229// #include <casacore/casa/Quanta.h>
230// Double myval; // keV photon energy
231// Quantity quant(myval,"keV"); // make quantity
232// cout << "A photon with energy " << quant << endl
233// << " has a frequency of "
234// << (quant/QC::h)->get("GHz") << endl // h=Planck
235// << " and a wavelength of "
236// << (QC::c/quant/QC::h)->get("nm") // c=light velocity
237// << " or " << QC::c/quant/QC::h << endl;
238// </srcblock>
239// </example>
240//
241// <motivation>
242// Major use is foreseen in all calculations with observed data.
243// </motivation>
244
245// <templating arg=Qtype>
246// <li> prefix +,-
247// <li> + - * / and += -= *= /=
248// <li> <src>< <= == != >= ></src>
249// <li> sin
250// <li> cos
251// <li> tan
252// <li> asin
253// <li> acos
254// <li> atan
255// <li> atan2
256// <li> abs
257// <li> ceil
258// <li> floor
259// <li> <note role=caution>
260// It is assumed that all these functions return either Bool or
261// the same data type as inputted (i.e. QType). Special functions are
262// provided in this module to convert Int and LogicalArray to Bool;
263// and to convert were necessary to Complex (e.g. abs(Complex)).
264// </note>
265// </templating>
266
267// <todo asof="941123">
268// <li> Some inlining (did not work first go)
269// </todo>
270
271template <class Qtype>
272class Quantum : public QBase {
273 // # Friends
274 // Input, only quantity is supported now
275 friend istream &operator>>(istream &is, Quantity &ku);
276
277 public:
278 // # Constructors
279 // Default constructor, generates '0'
281 // Copy constructor (deep copy)
282 Quantum(const Quantum<Qtype> &other);
283 // Construct undimensioned quantum (i.e. unit="")
284 Quantum(const Qtype &factor);
285 // Construct dimensioned quantum (e.g. '1.23 km/Mpc')
286 // <thrown>
287 // <li> AipsError if non-matching unit dimensions
288 // </thrown>
289 // <group>
290 Quantum(const Qtype &factor, const Unit &s);
291 // </group>
292 // Construct quantum with unit copied from existing quantum
293 Quantum(const Qtype &factor, const QBase &other);
294
295 // # Operators
296 // Assignment (deep copy)
298
299 // Unary operations
300 // <group>
301 const Quantum<Qtype> &operator+() const;
303 // </group>
304
305 // In place arithmetic functions: left hand side changed in place
306 // <thrown>
307 // <li> AipsError if non-conforming units (+ and -)
308 // <li> AipsError if illegal result unit (* and /; programming error)
309 // </thrown>
310 // <group>
312 Quantum<Qtype> &operator+=(const Qtype &other);
314 Quantum<Qtype> &operator-=(const Qtype &other);
316 Quantum<Qtype> &operator*=(const Qtype &other);
318 Quantum<Qtype> &operator/=(const Qtype &other);
319 // </group>
320
321 // Arithmetic operators: return Quantum<T>
322 // <thrown>
323 // <li> AipsError if non-conforming units (+ and -)
324 // </thrown>
325 // See <linkto group="QMath#Quantum mathematical operations">QMath</linkto> class for unequal
326 // argument types <group>
331 // </group>
332
333 // # General member functions
334 // Get value of quantum in current units (i.e. in units specified in quantum)
335 // <group>
336 const Qtype &getValue() const;
337 Qtype &getValue();
338 // </group>
339 // Get value in canonical base units
340 Qtype getBaseValue() const;
341
342 // Get value in specified units.
343 // If the <src>other</src> units do not conform to the units of this
344 // object and requireConform is True, an exception is thrown,
345 // with the following exceptions:
346 // <br>- angle to/from time conversions are implicitly supported
347 // <br>- frequency to/from/ wavelength conversions are implicitly supported
348 // # <br>Note, I added requireConform and made the default value False for
349 // # backward compatibility. However, I think that ultimately requireConform
350 // # should be removed and an exception should be thrown if the units do
351 // # not conform. It's not clear to me why this was not in the original
352 // # implementation; it's much too easy for non-conformation bugs to
353 // # slip by unnoticed. - dmehring 09feb2015
354 // # It should be left in since conversion from time to angle makes sense.
355 // # Maybe the default could be changed to True. - gvandiepen09feb2016
356 Qtype getValue(const Unit &other, Bool requireConform = False) const;
357
358 // Get the unit (as Unit) that is attached to the Quantum. (use getUnit() if
359 // interested in the String part only, e.g. for output)
360 virtual const Unit &getFullUnit() const;
361
362 // Re-specify parts of a quantum
363 // <group name="set value">
364 // Scale ( i.e. multiply) the value of the Quantum without changing units
365 void scale(const Qtype &factor);
366 // Set the value without changing units
367 void setValue(const Qtype &val);
368 // Set the value and unit deduced from input string
369 // <note role=caution> At the moment the implementation can only convert
370 // scalars to the appropiate Quantum. If format for Array input defined,
371 // it could easily be changed. In addition recognition of date/time/angle
372 // still has to be added </note>
373 // <group>
374 static Bool read(Quantity &res, const String &in);
375 static Bool read(Quantity &res, MUString &in);
376 // </group>
377 // </group>
378
379 // Check if of specified type
380 Bool check(const UnitVal &uv) const;
381
382 // Assert correct kind
383 // <thrown>
384 // <li> AipsError if non-conforming unit dimensions
385 // </thrown>
386 void assure(const UnitVal &uv) const;
387
388 // Return a Quantum converted to specified units
389 // <group name="get">
390 // Convert to canonical units
391 Quantum<Qtype> get() const;
392 // Convert to specified units; any remainder will be expressed in canonical
393 // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s .
394 // <thrown>
395 // <li> AipsError if illegal unit
396 // </thrown>
397 Quantum<Qtype> get(const Unit &s) const;
398 // Convert a Quantum to units from specified quantum (ibid example)
399 Quantum<Qtype> get(const Quantum<Qtype> &other) const;
400 // </group>
401
402 // Convert a Quantum to specified units
403 // <group>
404 // Convert to canonical units
405 void convert();
406 // Convert to specified units; any remainder will be expressed in canonical
407 // units. E.g. conversion of Jy/pc into W/ly2 will result in W/ly2.m-1.s .
408 // <thrown>
409 // <li> AipsError if illegal unit
410 // </thrown>
411 void convert(const Unit &s);
412 // Convert a Quantum to units from specified quantum (ibid example)
413 void convert(const Quantum<Qtype> &other);
414 // </group>
415 // Get a copy of Quantum
416 virtual QBase *clone() const;
417 // Print a Quantum
418 virtual void print(ostream &os) const;
419 // Get the type (using QuantumType) of derived Quantum (faster than Strings)
420 // <group>
421 virtual uInt type() const;
422 static uInt myType();
423 // </group>
424
425 private:
426 // # Data members
427 // Actual quantum value
428 Qtype qVal;
429};
430
431// Global functions
432// <summary> Global input function </summary>
433// Output/Input
434// <group name=output>
435// only Quantity is supported on input
436istream &operator>>(istream &is, Quantity &ku);
439// </group>
441// # Declare extern templates for often used types.
442extern template class Quantum<Double>;
443
444} // namespace casacore
445
446#ifndef CASACORE_NO_AUTO_TEMPLATES
447#include <casacore/casa/Quanta/Quantum.tcc>
448#endif // # CASACORE_NO_AUTO_TEMPLATES
449#endif
QBase()
Default constructor, generates "".
Quantum(const Quantum< Qtype > &other)
Copy constructor (deep copy).
Qtype & getValue()
Quantum(const Qtype &factor, const Unit &s)
Construct dimensioned quantum (e.g.
Quantum(const Qtype &factor, const QBase &other)
Construct quantum with unit copied from existing quantum.
Quantum< Qtype > & operator/=(const Qtype &other)
void convert()
Convert a Quantum to specified units.
void convert(const Quantum< Qtype > &other)
Convert a Quantum to units from specified quantum (ibid example).
virtual QBase * clone() const
Get a copy of Quantum.
Bool check(const UnitVal &uv) const
Check if of specified type.
Quantum< Qtype > operator*(const Quantum< Qtype > &other) const
virtual const Unit & getFullUnit() const
Get the unit (as Unit) that is attached to the Quantum.
Quantum< Qtype > get(const Unit &s) const
Convert to specified units; any remainder will be expressed in canonical units.
Quantum< Qtype > & operator/=(const Quantum< Qtype > &other)
Quantum< Qtype > & operator-=(const Quantum< Qtype > &other)
Quantum< Qtype > operator+(const Quantum< Qtype > &other) const
Arithmetic operators: return Quantum<T>.
void convert(const Unit &s)
Convert to specified units; any remainder will be expressed in canonical units.
void scale(const Qtype &factor)
Re-specify parts of a quantum .
Quantum< Qtype > get() const
Return a Quantum converted to specified units .
virtual void print(ostream &os) const
Print a Quantum.
Quantum< Qtype > operator/(const Quantum< Qtype > &other) const
Qtype getValue(const Unit &other, Bool requireConform=False) const
Get value in specified units.
Qtype getBaseValue() const
Get value in canonical base units.
Quantum< Qtype > & operator+=(const Qtype &other)
Quantum< Qtype > get(const Quantum< Qtype > &other) const
Convert a Quantum to units from specified quantum (ibid example).
Quantum< Qtype > & operator*=(const Qtype &other)
const Qtype & getValue() const
Get value of quantum in current units (i.e.
Quantum< Qtype > operator-() const
Quantum< Qtype > & operator+=(const Quantum< Qtype > &other)
In place arithmetic functions: left hand side changed in place.
virtual uInt type() const
Get the type (using QuantumType) of derived Quantum (faster than Strings).
Quantum< Qtype > & operator*=(const Quantum< Qtype > &other)
const Quantum< Qtype > & operator+() const
Unary operations.
Quantum(const Qtype &factor)
Construct undimensioned quantum (i.e.
static Bool read(Quantity &res, const String &in)
Set the value and unit deduced from input string Caution: At the moment the implementation can only ...
static uInt myType()
void assure(const UnitVal &uv) const
Assert correct kind.
void setValue(const Qtype &val)
Set the value without changing units.
Quantum()
Default constructor, generates '0'.
Quantum< Qtype > & operator=(const Quantum< Qtype > &other)
Assignment (deep copy).
static Bool read(Quantity &res, MUString &in)
Quantum< Qtype > operator-(const Quantum< Qtype > &other) const
Quantum< Qtype > & operator-=(const Qtype &other)
friend istream & operator>>(istream &is, Quantity &ku)
Input, only quantity is supported now.
String: the storage and methods of handling collections of characters.
Definition String.h:355
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
friend AipsIO & operator>>(AipsIO &os, Record &rec)
Read the Record from an input stream.
Definition Record.h:431
int * factor
Definition hdu.h:521
unsigned int uInt
Definition aipstype.h:49
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
Quantum< Double > Quantity
Definition Quantum.h:40
Bool readQuantity(Quantity &res, const String &in)
istream & operator>>(istream &is, Quantity &ku)
only Quantity is supported on input
Bool readQuantity(Quantity &res, MUString &in)