23 #ifndef PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED 24 #define PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED 36 #ifndef ENG_FORMAT_MICRO_GLYPH 37 # define ENG_FORMAT_MICRO_GLYPH "u" 52 char const *
const prefixes[][2][9] =
55 {
"",
"m", ENG_FORMAT_MICRO_GLYPH
56 ,
"n",
"p",
"f",
"a",
"z",
"y", },
57 {
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Z",
"Y", },
60 {
"e0",
"e-3",
"e-6",
"e-9",
"e-12",
"e-15",
"e-18",
"e-21",
"e-24", },
61 {
"e0",
"e3",
"e6",
"e9",
"e12",
"e15",
"e18",
"e21",
"e24", },
65 template<
typename T,
size_t N>
66 constexpr
size_t dimenson_of( T(&)[N] )
71 constexpr
int prefix_count = dimenson_of( prefixes[
false][
false] );
73 inline int sign(
int const value )
75 return value == 0 ? +1 : value /
std::abs( value );
78 inline bool iszero(
double const value )
80 return FP_ZERO == std::fpclassify( value );
83 inline long degree_of(
double const value )
85 return iszero( value ) ? 0 : std::lrint( std::floor( std::log10(
std::abs( value ) ) / 3) );
88 inline int precision(
double const scaled,
int const digits )
90 return iszero( scaled ) ? digits - 1 : digits - std::log10(
std::abs( scaled ) ) - 2 * std::numeric_limits<double>::epsilon();
93 inline std::string prefix_or_exponent(
bool const exponential,
int const degree )
95 return std::string( exponential || 0 == degree ?
"" :
" " ) + prefixes[ exponential ][ sign(degree) > 0 ][
std::abs( degree ) ];
98 inline std::string exponent(
int const degree )
100 std::ostringstream os;
101 os <<
"e" << 3 * degree;
105 inline std::string bracket( std::string
const unit )
107 return std::string::npos != unit.find_first_of(
"+- " ) ?
"(" + unit +
")" : unit;
116 to_engineering_string(
double const value,
int const digits = 3,
bool exponential =
false,
bool const showpos =
false, std::string
const unit =
"" )
118 using namespace detail;
120 if ( std::isnan( value ) )
return "NaN";
121 else if ( std::isinf( value ) )
return "INFINITE";
123 const int degree = degree_of( value );
127 if (
std::abs( degree ) < prefix_count )
129 factor = prefix_or_exponent( exponential, degree );
134 factor = exponent( degree );
137 std::ostringstream os;
139 const double scaled = value * std::pow( 1000.0, -degree );
141 const std::string space = ( 0 == degree || exponential ) && unit.length() ?
" ":
"";
143 os << std::fixed << (showpos ? std::showpos : std::noshowpos) << std::setprecision( precision(scaled, digits) ) << scaled << factor << space << bracket( unit );
151 template<
typename Dims,
typename T >
152 std::string
to_string(
quantity<Dims, T> const & q,
int const digits = 3,
bool const exponential =
false,
bool const showpos =
false )
157 template<
typename Dims,
typename T >
158 inline std::ostream & operator<<( std::ostream & os, quantity< Dims, T >
const & q )
168 #endif // PHYS_UNITS_QUANTITY_IO_ENGINEERING_HPP_INCLUDED quantity< D, X > constexpr abs(quantity< D, X > const &x)
absolute value.
std::string to_engineering_string(double const value, int const digits=3, bool exponential=false, bool const showpos=false, std::string const unit="")
convert real number to prefixed or exponential notation, optionally followed by a unit...
std::string to_unit_symbol(quantity< Dims, T > const &)
unit symbol.
std::string to_string(long double const value)
string representation of value.
class "quantity" is the heart of the library.
constexpr value_type magnitude() const
the quantity's magnitude.