Files
LBPM/common/Units.cpp
2018-05-15 10:01:14 -04:00

227 lines
7.9 KiB
C++

#include "common/Units.h"
#include "common/Utilities.h"
#include <algorithm>
#include <cmath>
#include <string>
constexpr double Units::d_pow10[22];
constexpr char Units::d_prefixSymbol[];
/********************************************************************
* Constructors *
********************************************************************/
Units::Units() : d_prefix( UnitPrefix::unknown ), d_unit( UnitValue::unknown ) {}
Units::Units( UnitPrefix p, UnitValue u ) : d_prefix( p ), d_unit( u ) {}
Units::Units( const std::string& unit )
: d_prefix( UnitPrefix::unknown ), d_unit( UnitValue::unknown )
{
// Parse the string to get it into a more friendly format
auto tmp = unit;
tmp.erase( std::remove( tmp.begin(), tmp.end(), ' ' ), tmp.end() );
// Check if the character '-' is present indicating a seperation between the prefix and unit
size_t index = tmp.find( '-' );
if ( index != std::string::npos ) {
d_prefix = getUnitPrefix( tmp.substr( 0, index ) );
d_unit = getUnitValue( tmp.substr( index + 1 ) );
} else {
if ( tmp.size() <= 1 ) {
d_prefix = UnitPrefix::none;
d_unit = getUnitValue( tmp );
} else if ( tmp.substr( 0, 2 ) == "da" ) {
d_prefix = UnitPrefix::deca;
d_unit = getUnitValue( tmp.substr( 2 ) );
} else {
d_prefix = getUnitPrefix( tmp.substr( 0, 1 ) );
d_unit = getUnitValue( tmp.substr( 1 ) );
if ( d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown ) {
d_prefix = UnitPrefix::none;
d_unit = getUnitValue( tmp );
}
}
}
}
/********************************************************************
* Get prefix *
********************************************************************/
Units::UnitPrefix Units::getUnitPrefix( const std::string& str ) noexcept
{
Units::UnitPrefix value = UnitPrefix::unknown;
if ( str.empty() ) {
value = UnitPrefix::none;
} else if ( str == "yotta" || str == "Y" ) {
value = UnitPrefix::yotta;
} else if ( str == "zetta" || str == "Z" ) {
value = UnitPrefix::zetta;
} else if ( str == "exa" || str == "E" ) {
value = UnitPrefix::exa;
} else if ( str == "peta" || str == "P" ) {
value = UnitPrefix::peta;
} else if ( str == "tera" || str == "T" ) {
value = UnitPrefix::tera;
} else if ( str == "giga" || str == "G" ) {
value = UnitPrefix::giga;
} else if ( str == "mega" || str == "M" ) {
value = UnitPrefix::mega;
} else if ( str == "kilo" || str == "k" ) {
value = UnitPrefix::kilo;
} else if ( str == "hecto" || str == "h" ) {
value = UnitPrefix::hecto;
} else if ( str == "deca" || str == "da" ) {
value = UnitPrefix::deca;
} else if ( str == "deci" || str == "d" ) {
value = UnitPrefix::deci;
} else if ( str == "centi" || str == "c" ) {
value = UnitPrefix::centi;
} else if ( str == "milli" || str == "m" ) {
value = UnitPrefix::milli;
} else if ( str == "micro" || str == "u" ) {
value = UnitPrefix::micro;
} else if ( str == "nano" || str == "n" ) {
value = UnitPrefix::nano;
} else if ( str == "pico" || str == "p" ) {
value = UnitPrefix::pico;
} else if ( str == "femto" || str == "f" ) {
value = UnitPrefix::femto;
} else if ( str == "atto" || str == "a" ) {
value = UnitPrefix::atto;
} else if ( str == "zepto" || str == "z" ) {
value = UnitPrefix::zepto;
} else if ( str == "yocto" || str == "y" ) {
value = UnitPrefix::yocto;
}
return value;
}
/********************************************************************
* Get unit value *
********************************************************************/
Units::UnitValue Units::getUnitValue( const std::string& str ) noexcept
{
Units::UnitValue value = UnitValue::unknown;
if ( str == "meter" || str == "m" ) {
value = UnitValue::meter;
} else if ( str == "gram" || str == "g" ) {
value = UnitValue::gram;
} else if ( str == "second" || str == "s" ) {
value = UnitValue::second;
} else if ( str == "ampere" || str == "A" ) {
value = UnitValue::ampere;
} else if ( str == "kelvin" || str == "K" ) {
value = UnitValue::kelvin;
} else if ( str == "joule" || str == "J" ) {
value = UnitValue::joule;
} else if ( str == "ergs" || str == "erg" ) {
value = UnitValue::erg;
} else if ( str == "degree" || str == "degrees" ) {
value = UnitValue::degree;
} else if ( str == "radian" || str == "radians" ) {
value = UnitValue::radian;
}
return value;
}
/********************************************************************
* Get unit type *
********************************************************************/
Units::UnitType Units::getUnitType( UnitValue u ) noexcept
{
switch ( u ) {
case UnitValue::meter:
return UnitType::length;
case UnitValue::gram:
return UnitType::mass;
case UnitValue::second:
return UnitType::time;
case UnitValue::ampere:
return UnitType::current;
case UnitValue::kelvin:
return UnitType::temperature;
case UnitValue::joule:
case UnitValue::erg:
return UnitType::energy;
case UnitValue::degree:
case UnitValue::radian:
return UnitType::angle;
default:
return UnitType::unknown;
}
}
/********************************************************************
* Convert to another unit system *
********************************************************************/
double Units::convert( const Units& rhs ) const noexcept
{
if ( this->operator==( rhs ) )
return 1;
// Convert the prefix
double cp = convert( d_prefix ) / convert( rhs.d_prefix );
if ( d_unit == rhs.d_unit )
return cp; // Only need to convert prefix
// Convert the unit
if ( getUnitType( d_unit ) != getUnitType( rhs.d_unit ) )
return 0; // Invalid conversion
double cu = 0;
if ( d_unit == UnitValue::joule && rhs.d_unit == UnitValue::erg )
cu = 1e7;
else if ( d_unit == UnitValue::erg && rhs.d_unit == UnitValue::joule )
cu = 1e-7;
else if ( d_unit == UnitValue::degree && rhs.d_unit == UnitValue::radian )
cu = 0.017453292519943;
else if ( d_unit == UnitValue::radian && rhs.d_unit == UnitValue::degree )
cu = 57.295779513082323;
// Return the total conversion
return cp * cu;
}
/********************************************************************
* Write a string for the units *
********************************************************************/
std::string Units::str() const
{
ASSERT( !isNull() );
return std::string( str( d_prefix ).data() ) + str( d_unit );
}
std::array<char, 3> Units::str( UnitPrefix p ) noexcept
{
std::array<char, 3> str;
str[0] = d_prefixSymbol[static_cast<int8_t>( p )];
str[1] = 0;
str[2] = 0;
if ( p == UnitPrefix::deca )
str[1] = 'a';
return str;
}
std::string Units::str( UnitValue u )
{
if ( u == UnitValue::meter ) {
return "m";
} else if ( u == UnitValue::gram ) {
return "g";
} else if ( u == UnitValue::second ) {
return "s";
} else if ( u == UnitValue::ampere ) {
return "A";
} else if ( u == UnitValue::kelvin ) {
return "K";
} else if ( u == UnitValue::joule ) {
return "J";
} else if ( u == UnitValue::erg ) {
return "erg";
} else if ( u == UnitValue::degree ) {
return "degree";
} else if ( u == UnitValue::radian ) {
return "radian";
}
return "unknown";
}