#include "common/Units.h" #include "common/Utilities.h" #include #include #include 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 Units::str( UnitPrefix p ) noexcept { std::array str; str[0] = d_prefixSymbol[static_cast( 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"; }