Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 103 additions & 19 deletions mojito/include/mojito/units/conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,40 @@

namespace mojito {

// SI <-> Per-Unit
template <typename Dim, typename Base>
constexpr auto to_si(const quantity<Dim, per_unit<Base>>& pu_quantity, const quantity<Dim, si>& base_quantity)
// SI/Physical <-> Per-Unit
template <typename Dim, typename System, typename Base>
constexpr auto to_si(const quantity<Dim, per_unit<Base>>& pu_quantity, const quantity<Dim, System>& base_quantity)
{
return quantity<Dim, si>(pu_quantity.value() * base_quantity.value());
return quantity<Dim, System>(pu_quantity.value() * base_quantity.value());
}

template <typename Base = default_base, typename Dim>
constexpr auto to_pu(const quantity<Dim, si>& si_quantity, const quantity<Dim, si>& base_quantity)
template <typename Base = default_base, typename Dim, typename System>
constexpr auto to_pu(const quantity<Dim, System>& si_quantity, const quantity<Dim, System>& base_quantity)
{
return quantity<Dim, per_unit<Base>>(si_quantity.value() / base_quantity.value());
}

template <typename Base = default_base, typename Dim>
constexpr auto to_pu(const quantity<Dim, si>& si_quantity, const divisor<quantity<Dim, si>>& divisor)
template <typename Base = default_base, typename Dim, typename System>
constexpr auto to_pu(const quantity<Dim, System>& si_quantity, const divisor<quantity<Dim, System>>& divisor)
{
return quantity<Dim, per_unit<Base>>(si_quantity.value() * divisor.reciprocal());
}

template <typename Dim, typename Base>
constexpr auto to_si(const quantity<Dim, per_unit<Base>>& pu_quantity, const divisor<quantity<Dim, si>>& divisor)
template <typename Dim, typename System, typename Base>
constexpr auto to_si(const quantity<Dim, per_unit<Base>>& pu_quantity, const divisor<quantity<Dim, System>>& divisor)
{
return quantity<Dim, si>(pu_quantity.value() * divisor.value().value());
return quantity<Dim, System>(pu_quantity.value() * divisor.value().value());
}

// SI <-> Percent
template <typename Dim>
constexpr auto to_si(const quantity<Dim, percent>& percent_quantity, const quantity<Dim, si>& base_quantity)
// SI/Physical <-> Percent
template <typename Dim, typename System>
constexpr auto to_si(const quantity<Dim, percent>& percent_quantity, const quantity<Dim, System>& base_quantity)
{
return quantity<Dim, si>((percent_quantity.value() / real_t{100.0}) * base_quantity.value());
return quantity<Dim, System>((percent_quantity.value() / real_t{100.0}) * base_quantity.value());
}

template <typename Dim>
constexpr auto to_percent(const quantity<Dim, si>& si_quantity, const quantity<Dim, si>& base_quantity)
template <typename Dim, typename System>
constexpr auto to_percent(const quantity<Dim, System>& si_quantity, const quantity<Dim, System>& base_quantity)
{
return quantity<Dim, percent>((si_quantity.value() / base_quantity.value()) * real_t{100.0});
}
Expand All @@ -58,13 +58,97 @@ constexpr auto to_pu(const quantity<Dim, percent>& percent_quantity)
}

// Per-Unit <-> Per-Unit
template <typename NewBase, typename OldBase, typename Dim>
template <typename NewBase, typename OldBase, typename Dim, typename System>
constexpr auto to_different_pu(const quantity<Dim, per_unit<OldBase>>& pu_quantity,
const quantity<Dim, si>& old_base_quantity, const quantity<Dim, si>& new_base_quantity)
const quantity<Dim, System>& old_base_quantity, const quantity<Dim, System>& new_base_quantity)
{
return to_pu<NewBase>(to_si(pu_quantity, old_base_quantity), new_base_quantity);
}

// Time conversions
template <typename Unit>
struct time_conversion_factor;

template <>
struct time_conversion_factor<si> {
static constexpr real_t value = real_t{1.0};
};

template <>
struct time_conversion_factor<microseconds> {
static constexpr real_t value = real_t{1e-6};
};

template <>
struct time_conversion_factor<milliseconds> {
static constexpr real_t value = real_t{1e-3};
};

template <>
struct time_conversion_factor<minutes> {
static constexpr real_t value = real_t{60.0};
};

template <>
struct time_conversion_factor<hours> {
static constexpr real_t value = real_t{3600.0};
};

namespace internal {
template <typename T, typename = void>
struct extract_system {
using type = T;
};

template <typename T>
struct extract_system<T, std::void_t<typename T::system>> {
using type = typename T::system;
};

template <typename T>
using extract_system_t = typename extract_system<T>::type;
} // namespace internal

template <typename To, typename FromSystem>
constexpr auto time_cast(const quantity<time_dim, FromSystem>& q)
{
using ToSystem = internal::extract_system_t<To>;
constexpr real_t factor_from = time_conversion_factor<FromSystem>::value;
constexpr real_t factor_to = time_conversion_factor<ToSystem>::value;
return quantity<time_dim, ToSystem>(q.value() * (factor_from / factor_to));
}

// Convenience converters
template <typename FromSystem>
constexpr auto to_us(const quantity<time_dim, FromSystem>& q)
{
return time_cast<microseconds>(q);
}

template <typename FromSystem>
constexpr auto to_ms(const quantity<time_dim, FromSystem>& q)
{
return time_cast<milliseconds>(q);
}

template <typename FromSystem>
constexpr auto to_seconds(const quantity<time_dim, FromSystem>& q)
{
return time_cast<seconds>(q);
}

template <typename FromSystem>
constexpr auto to_minutes(const quantity<time_dim, FromSystem>& q)
{
return time_cast<minutes>(q);
}

template <typename FromSystem>
constexpr auto to_hours(const quantity<time_dim, FromSystem>& q)
{
return time_cast<hours>(q);
}

// Casting
template <typename NewType, typename OldDim, typename OldBase>
constexpr auto per_unit_cast(const quantity<OldDim, per_unit<OldBase>>& q)
Expand Down
4 changes: 4 additions & 0 deletions mojito/include/mojito/units/formatting.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ std::ostream& operator<<(std::ostream& os, const quantity<Dim, UnitSystem>& q)
{
os << q.value();
if constexpr (std::is_same_v<UnitSystem, si>) os << internal::get_unit_symbol<Dim>();
else if constexpr (std::is_same_v<UnitSystem, microseconds>) os << " us";
else if constexpr (std::is_same_v<UnitSystem, milliseconds>) os << " ms";
else if constexpr (std::is_same_v<UnitSystem, minutes>) os << " min";
else if constexpr (std::is_same_v<UnitSystem, hours>) os << " h";
else if constexpr (is_per_unit_v<UnitSystem>) os << " pu";
else if constexpr (std::is_same_v<UnitSystem, percent>) os << " %";
return os;
Expand Down
41 changes: 41 additions & 0 deletions mojito/include/mojito/units/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,45 @@ constexpr bool operator>=(const quantity<D, S>& q, Arithmetic val)
return q.value() >= static_cast<real_t>(val);
}

// Prevent operations between mismatched dimensions or unit systems
template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator+(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator-(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<S1, S2>>>
void operator*(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<S1, S2>>>
void operator/(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator==(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator!=(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator<(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator<=(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator>(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

template <typename D1, typename S1, typename D2, typename S2,
typename = std::enable_if_t<!std::is_same_v<D1, D2> || !std::is_same_v<S1, S2>>>
void operator>=(const quantity<D1, S1>&, const quantity<D2, S2>&) = delete;

} // namespace mojito
15 changes: 15 additions & 0 deletions mojito/include/mojito/units/systems.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,23 @@ namespace mojito {

struct si {};

// Time Unit Systems
struct microseconds {};
struct milliseconds {};
using seconds = si;
struct minutes {};
struct hours {};

struct default_base {};

// Time Base Tags
struct microseconds_base {};
struct milliseconds_base {};
struct seconds_base {};
struct minutes_base {};
struct hours_base {};


template <typename Base = default_base>
struct per_unit {
using base = Base;
Expand Down
20 changes: 20 additions & 0 deletions mojito/include/mojito/units/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ namespace mojito {
using length_t = quantity<length_dim, si>;
using mass_t = quantity<mass_dim, si>;
using duration_t = quantity<time_dim, si>;
using microseconds_t = quantity<time_dim, microseconds>;
using milliseconds_t = quantity<time_dim, milliseconds>;
using seconds_t = quantity<time_dim, seconds>;
using minutes_t = quantity<time_dim, minutes>;
using hours_t = quantity<time_dim, hours>;
using current_t = quantity<current_dim, si>;
using speed_t = quantity<speed_dim, si>;
using acceleration_t = quantity<acceleration_dim, si>;
Expand All @@ -35,6 +40,11 @@ using inertia_constant_t = quantity<time_dim, si>;
using length_pu_t = quantity<length_dim, per_unit<default_base>>;
using mass_pu_t = quantity<mass_dim, per_unit<default_base>>;
using duration_pu_t = quantity<time_dim, per_unit<default_base>>;
using microseconds_pu_t = quantity<time_dim, per_unit<microseconds_base>>;
using milliseconds_pu_t = quantity<time_dim, per_unit<milliseconds_base>>;
using seconds_pu_t = quantity<time_dim, per_unit<seconds_base>>;
using minutes_pu_t = quantity<time_dim, per_unit<minutes_base>>;
using hours_pu_t = quantity<time_dim, per_unit<hours_base>>;
using speed_pu_t = quantity<speed_dim, per_unit<default_base>>;
using acceleration_pu_t = quantity<acceleration_dim, per_unit<default_base>>;
using frequency_pu_t = quantity<frequency_dim, per_unit<default_base>>;
Expand All @@ -60,6 +70,11 @@ using inertia_constant_pu_t = quantity<time_dim, per_unit<default_base>>;
template <typename Base> using length_custom_pu_t = quantity<length_dim, per_unit<Base>>;
template <typename Base> using mass_custom_pu_t = quantity<mass_dim, per_unit<Base>>;
template <typename Base> using duration_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using microseconds_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using milliseconds_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using seconds_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using minutes_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using hours_custom_pu_t = quantity<time_dim, per_unit<Base>>;
template <typename Base> using speed_custom_pu_t = quantity<speed_dim, per_unit<Base>>;
template <typename Base> using acceleration_custom_pu_t = quantity<acceleration_dim, per_unit<Base>>;
template <typename Base> using frequency_custom_pu_t = quantity<frequency_dim, per_unit<Base>>;
Expand All @@ -85,6 +100,11 @@ template <typename Base> using inertia_constant_custom_pu_t = quantity<time_dim,
using length_percent_t = quantity<length_dim, percent>;
using mass_percent_t = quantity<mass_dim, percent>;
using duration_percent_t = quantity<time_dim, percent>;
using microseconds_percent_t = quantity<time_dim, percent>;
using milliseconds_percent_t = quantity<time_dim, percent>;
using seconds_percent_t = quantity<time_dim, percent>;
using minutes_percent_t = quantity<time_dim, percent>;
using hours_percent_t = quantity<time_dim, percent>;
using speed_percent_t = quantity<speed_dim, percent>;
using acceleration_percent_t = quantity<acceleration_dim, percent>;
using frequency_percent_t = quantity<frequency_dim, percent>;
Expand Down
36 changes: 36 additions & 0 deletions mojito/modules/mojito.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,17 @@ using ::mojito::is_coordinate_frame_v;
// units.hpp
using ::mojito::dimension;
using ::mojito::si;
using ::mojito::microseconds;
using ::mojito::milliseconds;
using ::mojito::seconds;
using ::mojito::minutes;
using ::mojito::hours;
using ::mojito::default_base;
using ::mojito::microseconds_base;
using ::mojito::milliseconds_base;
using ::mojito::seconds_base;
using ::mojito::minutes_base;
using ::mojito::hours_base;
using ::mojito::per_unit;
using ::mojito::is_per_unit_v;
using ::mojito::percent;
Expand Down Expand Up @@ -77,6 +87,11 @@ using ::mojito::flux_density_dim;
using ::mojito::length_t;
using ::mojito::mass_t;
using ::mojito::duration_t;
using ::mojito::microseconds_t;
using ::mojito::milliseconds_t;
using ::mojito::seconds_t;
using ::mojito::minutes_t;
using ::mojito::hours_t;
using ::mojito::current_t;
using ::mojito::speed_t;
using ::mojito::acceleration_t;
Expand All @@ -102,6 +117,11 @@ using ::mojito::inertia_constant_t;
using ::mojito::length_pu_t;
using ::mojito::mass_pu_t;
using ::mojito::duration_pu_t;
using ::mojito::microseconds_pu_t;
using ::mojito::milliseconds_pu_t;
using ::mojito::seconds_pu_t;
using ::mojito::minutes_pu_t;
using ::mojito::hours_pu_t;
using ::mojito::speed_pu_t;
using ::mojito::acceleration_pu_t;
using ::mojito::frequency_pu_t;
Expand All @@ -127,6 +147,11 @@ using ::mojito::inertia_constant_pu_t;
using ::mojito::length_custom_pu_t;
using ::mojito::mass_custom_pu_t;
using ::mojito::duration_custom_pu_t;
using ::mojito::microseconds_custom_pu_t;
using ::mojito::milliseconds_custom_pu_t;
using ::mojito::seconds_custom_pu_t;
using ::mojito::minutes_custom_pu_t;
using ::mojito::hours_custom_pu_t;
using ::mojito::speed_custom_pu_t;
using ::mojito::acceleration_custom_pu_t;
using ::mojito::frequency_custom_pu_t;
Expand All @@ -152,6 +177,11 @@ using ::mojito::inertia_constant_custom_pu_t;
using ::mojito::length_percent_t;
using ::mojito::mass_percent_t;
using ::mojito::duration_percent_t;
using ::mojito::microseconds_percent_t;
using ::mojito::milliseconds_percent_t;
using ::mojito::seconds_percent_t;
using ::mojito::minutes_percent_t;
using ::mojito::hours_percent_t;
using ::mojito::speed_percent_t;
using ::mojito::acceleration_percent_t;
using ::mojito::frequency_percent_t;
Expand Down Expand Up @@ -221,5 +251,11 @@ using ::mojito::max;
using ::mojito::min;
using ::mojito::per_unit_cast;
using ::mojito::percent_cast;
using ::mojito::time_cast;
using ::mojito::to_us;
using ::mojito::to_ms;
using ::mojito::to_seconds;
using ::mojito::to_minutes;
using ::mojito::to_hours;

} // namespace mojito
Loading
Loading