//# Quantum.cc: class to manipulate physical, dimensioned quantities //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2003,2004 //# 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.tcc 20993 2010-11-08 13:36:32Z gervandiepen $ #ifndef CASA_QUANTUM_TCC #define CASA_QUANTUM_TCC //# Includes #include #include #include #include #include #include #include #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN template Quantum::Quantum() : QBase() { qVal = Qtype();} template Quantum::Quantum(const Quantum &other) : QBase(other) { // Here qVal is copy-assigned in the constructor body // instead of direct-initialized in the member initializer list (which invokes // its copy constructor) to cope with Array/Vector/Matrix values: they copy by // reference on the copy construction, but by value on copy assignment (and // this class wants to do the latter). // See https://github.com/casacore/casacore/commit/e5d8484b5108f0a890ddd9d494c2efcab738ce7c#r42799565 // for reference qVal = other.qVal; } template Quantum::Quantum(const Qtype &factor) : QBase() { qVal = factor; } template Quantum::Quantum(const Qtype &factor, const Unit &s) : QBase(s) { qVal = factor; } template Quantum::Quantum(const Qtype &factor, const QBase &other) : QBase(other) { qVal = factor; } //# Quantum operators template Quantum &Quantum::operator=(const Quantum &/*other*/) = default; template const Quantum &Quantum::operator+() const{ return *this; } template Quantum Quantum::operator-() const{ Quantum loc; loc.qVal = -qVal; loc.qUnit = qUnit; return loc; } template Quantum &Quantum::operator+=(const Quantum &other) { if (qUnit.getValue() != other.qUnit.getValue()) { throw (AipsError("Quantum::operator+ unequal units '" + qUnit.getName() + ", '" + other.qUnit.getName() + "'")); } else { Qtype tmp = other.getValue(qUnit); qVal += (tmp); } return *this; } template Quantum &Quantum::operator+=(const Qtype &other) { qVal += other; return *this; } template Quantum &Quantum::operator-=(const Quantum &other) { if (qUnit.getValue() != other.qUnit.getValue()) { throw (AipsError("Quantum::operator- unequal units '" + qUnit.getName() + ", '" + other.qUnit.getName() + "'")); } else { Qtype tmp = other.getValue(qUnit); qVal -= (tmp); } return *this; } template Quantum &Quantum::operator-=(const Qtype &other) { qVal -= (other); return *this; } template Quantum &Quantum::operator*=(const Quantum &other) { qVal *= (other.qVal); if (!(other.qUnit.getName().empty())) { if (qUnit.getName().empty()) { qUnit = other.qUnit; } else { qUnit = Unit(qUnit.getName() + ("." + other.qUnit.getName())); } } return *this; } template Quantum &Quantum::operator*=(const Qtype &other) { qVal *= (other); return *this; } template Quantum &Quantum::operator/=(const Quantum &other) { qVal /= (other.qVal); if (!(other.qUnit.getName().empty())) { if (qUnit.getName().empty()) { qUnit = Unit(String("(") + other.qUnit.getName() + String(")-1")); } else { qUnit = Unit(qUnit.getName() + ("/(" + other.qUnit.getName() + ")")); } } return *this; } template Quantum &Quantum::operator/=(const Qtype &other) { qVal /= (other); return *this; } template Quantum Quantum::operator+(const Quantum &other) const{ Quantum loc; loc = *this; loc += other; return loc; } template Quantum Quantum::operator-(const Quantum &other) const{ Quantum loc; loc = *this; loc -= other; return loc; } template Quantum Quantum::operator*(const Quantum &other) const{ Quantum loc; loc = *this; loc *= other; return loc; } template Quantum Quantum::operator/(const Quantum &other) const{ Quantum loc; loc = *this; loc /= other; return loc; } template void Quantum::print(ostream &os) const { os << qVal << " " << qUnit.getName(); } //# Quantum general member functions template const Qtype &Quantum::getValue() const { return qVal; } template Qtype & Quantum::getValue() { return qVal; } template Qtype Quantum::getValue(const Unit &other, Bool requireConform) const { UnitVal myType = qUnit.getValue(); UnitVal otherType = other.getValue(); Double myFac = myType.getFac(); Double otherFac = otherType.getFac(); Double d1 = otherFac/myFac; if (myType == otherType) { return (Qtype)(qVal/d1); } if ( myType == UnitVal::ANGLE && otherType == UnitVal::TIME ) { d1 *= C::circle/C::day; } else if ( myType == UnitVal::TIME && otherType == UnitVal::ANGLE ) { d1 *= C::day/C::circle; } else if( myType == 1/UnitVal::TIME && otherType == UnitVal::LENGTH ) { return (Qtype)(C::c/qVal/myFac/otherFac); } else if( myType == UnitVal::LENGTH && otherType == 1/UnitVal::TIME ) { return (Qtype)(C::c/qVal/myFac/otherFac); } else if (requireConform) { ThrowCc( "From/to units not consistent. Cannot convert " + qUnit.getName() + " to " + other.getName() ); } return (Qtype)(qVal/d1); } template Qtype Quantum::getBaseValue() const { return (Qtype)(qVal * qUnit.getValue().getFac()); } template const Unit &Quantum::getFullUnit() const { return qUnit; } template void Quantum::scale(const Qtype &factor) { qVal *= (factor); } template void Quantum::setValue(const Qtype &val) { qVal = val; } template Bool Quantum::read(Quantity &res, MUString &in) { return readQuantity(res, in); } template Bool Quantum::read(Quantity &res, const String &in) { return readQuantity(res, in); } template Bool Quantum::check(const UnitVal &uv) const { return ( (qUnit.getValue() == uv) ? True : False); } template void Quantum::assure(const UnitVal &uv) const { if (qUnit.getValue() != uv) { throw(AipsError("Quantum::assure non-conforming unit type '" + getUnit() + "'")); } } template void Quantum::convert() { this->convert(Unit()); } template void Quantum::convert(const Unit &s) { if (qUnit.getValue() == s.getValue()) { // To suppress some warnings, next statement not used // qVal *= (qUnit.getValue().getFac()/s.getValue().getFac()); qVal = Qtype (qVal * (qUnit.getValue().getFac()/s.getValue().getFac())); qUnit = s; } else { if (qUnit.getValue() == UnitVal::ANGLE && s.getValue() == UnitVal::TIME) { qVal = Qtype (qVal * (qUnit.getValue().getFac()/s.getValue().getFac()) * C::day/C::circle); qUnit = s; } else if (qUnit.getValue() == UnitVal::TIME && s.getValue() == UnitVal::ANGLE) { qVal = Qtype (qVal * (qUnit.getValue().getFac()/s.getValue().getFac()) * C::circle/C::day); qUnit = s; } else { qUnit.setValue(qUnit.getValue() / s.getValue()); ostringstream oss; oss << qUnit.getValue().getDim(); // Suppress (gcc) warnings: qVal = Qtype (qVal * qUnit.getValue().getFac()); if (s.empty()) { qUnit = String(oss); } else { qUnit = Unit(s.getName() + '.' + String(oss).after(0)); } } } } template void Quantum::convert(const Quantum &other) { this->convert(other.qUnit); } template Quantum Quantum::get() const { return get(Unit()); } template Quantum Quantum::get(const Unit &s) const { Quantum res = *this; res.convert(s); return res; } template Quantum Quantum::get(const Quantum &other) const{ return get(other.qUnit); } template QBase *Quantum::clone() const { return (new Quantum(*this)); } template uInt Quantum::type() const { return quantumType (static_cast *>(0)); } template uInt Quantum::myType() { return quantumType (static_cast *>(0)); } } //# NAMESPACE CASACORE - END #endif