Skip to content

Commit

Permalink
Units: mass has microgram (μg) precision
Browse files Browse the repository at this point in the history
Vitamins are often present in very small quantities, so to specify
vitamins by weight, more precision that 1mg is required for mass.

This changes mass from the smallest unit being 1mg to the smallest unit
being 1μg.
The range of representable values were previously:
~9 petagrams (24x the biomass of all living humans) to 1mg
Now the range of representable values are:
~9 teragrams (~1.5x the mass of the Great Pyramid of Giza) to 1μg

Both 'μg' and 'ug' are supported when representing mass strings in JSON.
  • Loading branch information
ehughsbaird committed Oct 29, 2023
1 parent 033a9b7 commit a89552d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
49 changes: 36 additions & 13 deletions src/units.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,41 +334,54 @@ const mass mass_max = units::mass( std::numeric_limits<units::mass::value_type>:
units::mass::unit_type{} );

template<typename value_type>
inline constexpr quantity<value_type, mass_in_milligram_tag> from_milligram(
inline constexpr quantity<value_type, mass_in_microgram_tag> from_microgram(
const value_type v )
{
return quantity<value_type, mass_in_milligram_tag>( v, mass_in_milligram_tag{} );
return quantity<value_type, mass_in_microgram_tag>( v, mass_in_microgram_tag{} );
}

template<typename value_type>
inline constexpr quantity<value_type, mass_in_milligram_tag> from_gram(
inline constexpr quantity<value_type, mass_in_microgram_tag> from_milligram(
const value_type v )
{
return from_microgram( v * 1000 );
}

template<typename value_type>
inline constexpr quantity<value_type, mass_in_microgram_tag> from_gram(
const value_type v )
{
return from_milligram( v * 1000 );
}

template<typename value_type>
inline constexpr quantity<value_type, mass_in_milligram_tag> from_kilogram(
inline constexpr quantity<value_type, mass_in_microgram_tag> from_kilogram(
const value_type v )
{
return from_gram( v * 1000 );
}

template<typename value_type>
inline constexpr value_type to_milligram( const quantity<value_type, mass_in_milligram_tag> &v )
inline constexpr value_type to_microgram( const quantity<value_type, mass_in_microgram_tag> &v )
{
return v.value();
}

template<typename value_type>
inline constexpr value_type to_gram( const quantity<value_type, mass_in_milligram_tag> &v )
inline constexpr value_type to_milligram( const quantity<value_type, mass_in_microgram_tag> &v )
{
return v.value() / 1000.0;
}

template<typename value_type>
inline constexpr value_type to_gram( const quantity<value_type, mass_in_microgram_tag> &v )
{
return v.value() / 1'000'000.0;
}

inline constexpr double to_kilogram( const mass &v )
{
return v.value() / 1000000.0;
return v.value() / 1'000'000'000.0;
}

// Specific energy
Expand Down Expand Up @@ -783,9 +796,9 @@ inline constexpr quantity<value_type, length_in_millimeter_tag> default_length_f
// Streaming operators for debugging and tests
// (for UI output other functions should be used which render in the user's
// chosen units)
inline std::ostream &operator<<( std::ostream &o, mass_in_milligram_tag )
inline std::ostream &operator<<( std::ostream &o, mass_in_microgram_tag )
{
return o << "mg";
return o << "μg";
}

inline std::ostream &operator<<( std::ostream &o, volume_in_milliliter_tag )
Expand Down Expand Up @@ -867,7 +880,10 @@ inline constexpr units::quantity<double, units::volume_in_milliliter_tag> operat
return units::from_milliliter( v * 1000 );
}

// Implicitly converted to mass, which has int as value_type!
inline constexpr units::mass operator"" _microgram( const unsigned long long v )
{
return units::from_microgram( v );
}
inline constexpr units::mass operator"" _milligram( const unsigned long long v )
{
return units::from_milligram( v );
Expand All @@ -882,19 +898,24 @@ inline constexpr units::mass operator"" _kilogram( const unsigned long long v )
return units::from_kilogram( v );
}

inline constexpr units::quantity<double, units::mass_in_milligram_tag> operator"" _milligram(
inline constexpr units::quantity<double, units::mass_in_microgram_tag> operator"" _microgram(
const long double v )
{
return units::from_microgram( v );
}
inline constexpr units::quantity<double, units::mass_in_microgram_tag> operator"" _milligram(
const long double v )
{
return units::from_milligram( v );
}

inline constexpr units::quantity<double, units::mass_in_milligram_tag> operator"" _gram(
inline constexpr units::quantity<double, units::mass_in_microgram_tag> operator"" _gram(
const long double v )
{
return units::from_gram( v );
}

inline constexpr units::quantity<double, units::mass_in_milligram_tag> operator"" _kilogram(
inline constexpr units::quantity<double, units::mass_in_microgram_tag> operator"" _kilogram(
const long double v )
{
return units::from_kilogram( v );
Expand Down Expand Up @@ -1147,6 +1168,8 @@ const std::vector<std::pair<std::string, power>> power_units = { {
}
};
const std::vector<std::pair<std::string, mass>> mass_units = { {
{ "ug", 1_microgram },
{ "μg", 1_microgram },
{ "mg", 1_milligram },
{ "g", 1_gram },
{ "kg", 1_kilogram },
Expand Down
4 changes: 2 additions & 2 deletions src/units_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ class volume_in_milliliter_tag

using volume = quantity<int, volume_in_milliliter_tag>;

class mass_in_milligram_tag
class mass_in_microgram_tag
{
};

using mass = quantity<std::int64_t, mass_in_milligram_tag>;
using mass = quantity<std::int64_t, mass_in_microgram_tag>;

class specific_energy_in_joule_per_gram_tag
{
Expand Down

0 comments on commit a89552d

Please sign in to comment.