Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Magnitude instead of ratio in unit implementations #355

Merged
merged 38 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bc98254
Support `-` and `<=>` in `ratio`
chiphogg Apr 9, 2022
af8eec1
Implement "common Magnitude" of two Magnitudes
chiphogg Apr 9, 2022
85d6e35
Loosen requirements on Rep for Magnitude
chiphogg Apr 9, 2022
5c0eb06
Remove `inverse_if_negative()`
chiphogg Apr 9, 2022
5afe776
Use Magnitude implementation for `base_units_ratio`
chiphogg Apr 9, 2022
d19b280
Migrate units from ratio to Magnitude
chiphogg Apr 9, 2022
5e365f1
Delete obsolete test case
chiphogg Apr 9, 2022
7a03692
Annotate 225'653'407'801 as prime
chiphogg Apr 12, 2022
78bcb3b
Remove troublesome `::ratio` members
chiphogg Apr 12, 2022
c805a93
Implement suggestion
chiphogg Apr 12, 2022
94fe48d
Add <compare> to satisfy clang
chiphogg Apr 12, 2022
2b37bc7
Address review feedback
chiphogg Apr 19, 2022
bd5a476
fix: `pow<>` requires a `ratio` as a template argument
mpusz May 11, 2022
104923d
refactor: `as_ratio()` constrain simplified
mpusz May 11, 2022
b3afd61
refactor: duplicated concepts checks removed to improve compile times
mpusz May 11, 2022
54489a5
refactor: missing constraints on a return type added
mpusz May 11, 2022
0ed43d3
fix: restoring original `as_magnitude` implementation as it was correct
mpusz May 11, 2022
0765fb2
fix: MSVC complains that an address of NTTP is taken here
mpusz May 12, 2022
5fb4686
Merge branch 'master' into chiphogg/switch-to-mag
chiphogg May 12, 2022
59fa420
Fix remaining builds/tests
chiphogg May 12, 2022
a0ac140
Merge fixes into branch after updating with upstream changes
chiphogg May 12, 2022
88a69ce
Try fixing build
chiphogg May 12, 2022
f36205f
Capture NTTP in variable
chiphogg May 12, 2022
2bdc778
Constrain template
chiphogg May 12, 2022
86b81c9
Undo misguided fix attempt
chiphogg May 12, 2022
6c1062e
fix: `UNITS_MSVC_WORKAROUND()` added
mpusz May 14, 2022
b559a5f
fix: explicit `ratio` creation added as a workaround for MSVC
mpusz May 14, 2022
43844c4
fix: `UNITS_MSVC_WORKAROUND()` fixed for other compilers
mpusz May 14, 2022
db09a06
refactor: :boom: ! " ⋅ " replaced with "⋅" in derived unit symbols
mpusz May 24, 2022
46b3781
Revert "refactor: :boom: ! " ⋅ " replaced with "⋅" in derived unit sy…
mpusz May 24, 2022
a8625d3
docs: P0847 reference removed
mpusz Jun 6, 2022
9a6d6f9
fix: MSVC conversion issues fixed
mpusz Jun 9, 2022
f5e6d05
fix: MSVC compilation error workaround
mpusz Jun 9, 2022
ef9e652
Merge branch 'master' into chiphogg/switch-to-mag
chiphogg Jun 15, 2022
6d66ac5
Migrate new `lumen` as well
chiphogg Jun 15, 2022
c8ec771
Help factoring for eV/c
chiphogg Jun 15, 2022
3916b29
Move known_first_factor specialization outside namespace
chiphogg Jun 15, 2022
f004854
Remove useful names to appease MSVC 14
chiphogg Jun 15, 2022
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
8 changes: 4 additions & 4 deletions example/custom_systems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ using namespace units;
namespace fps {

struct foot : named_unit<foot, "ft"> {};
struct yard : named_scaled_unit<yard, "yd", ratio(3), foot> {};
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};

struct dim_length : base_dimension<"L", foot> {};

Expand All @@ -54,8 +54,8 @@ using length = quantity<dim_length, U, Rep>;

namespace fps {

struct foot : named_scaled_unit<foot, "ft", ratio(3'048, 1'000, -1), metre> {};
struct yard : named_scaled_unit<yard, "yd", ratio(3), foot> {};
struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {};
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};

struct dim_length : base_dimension<"L", foot> {};

Expand Down Expand Up @@ -103,7 +103,7 @@ template<Unit U>
std::ostream& operator<<(std::ostream& os, const U& u)
{
using unit_type = std::remove_cvref_t<decltype(u)>;
return os << unit_type::ratio << " x " << unit_type::reference::symbol.standard();
return os << as_ratio(unit_type::mag) << " x " << unit_type::reference::symbol.standard();
}

void what_is_your_ratio()
Expand Down
26 changes: 11 additions & 15 deletions src/core/include/units/bits/base_units_ratio.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,25 @@

#include <units/base_dimension.h>
#include <units/exponent.h>
#include <units/magnitude.h>
#include <units/ratio.h>

namespace units::detail {

template<Exponent E>
requires(E::den == 1 || E::den == 2) // TODO provide support for any den
constexpr ratio exp_ratio()
{
const ratio base_ratio = E::dimension::base_unit::ratio;
const ratio positive_ratio =
E::num * E::den < 0 ? ratio(base_ratio.den, base_ratio.num, -base_ratio.exp) : base_ratio;
const std::intmax_t N = E::num * E::den < 0 ? -E::num : E::num;
const ratio ratio_pow = pow<N>(positive_ratio);
return E::den == 2 ? sqrt(ratio_pow) : ratio_pow;
}

/**
* @brief Calculates the common ratio of all the references of base units in the derived dimension
* @brief Calculates the "absolute" magnitude of the derived dimension defined by this list.
*
* "Absolute" magnitudes are not physically observable: only ratios of magnitudes are. For example: if we multiplied
* all magnitudes in the system by the same constant, no meaningful results would change. However, in practice, we need
* to make some global choice for the "absolute" values of magnitudes, so that we can compute their ratios.
*
* The point of this function is to compute the absolute magnitude of a derived dimension, in terms of the absolute
* magnitudes of its constituent dimensions.
*/
template<typename... Es>
constexpr ratio base_units_ratio(exponent_list<Es...>)
constexpr Magnitude auto absolute_magnitude(exponent_list<Es...>)
{
return (exp_ratio<Es>() * ... * ratio(1));
return (pow<ratio{Es::num, Es::den}>(Es::dimension::base_unit::mag) * ... * magnitude<>{});
}

} // namespace units::detail
17 changes: 4 additions & 13 deletions src/core/include/units/bits/basic_concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <units/bits/external/fixed_string.h>
#include <units/bits/external/type_traits.h>
#include <units/customization_points.h>
#include <units/ratio.h>
#include <units/magnitude.h>
// IWYU pragma: end_exports

#include <cstdint>
Expand Down Expand Up @@ -56,24 +56,15 @@ void to_prefix_base(const volatile prefix_base<R>*);
template<typename T>
concept Prefix = requires(T* t) { detail::to_prefix_base(t); };

/**
* @brief A concept matching unit's ratio
*
* Satisfied by all ratio values for which `R.num > 0` and `R.den > 0`.
*/
template<ratio R>
concept UnitRatio = (R.num > 0) && (R.den > 0);

// Unit
template<ratio R, typename U>
requires UnitRatio<R>
template<Magnitude auto M, typename U>
struct scaled_unit;

// TODO: Remove when P1985 accepted
namespace detail {

template<ratio R, typename U>
void to_base_scaled_unit(const volatile scaled_unit<R, U>*);
template<Magnitude auto M, typename U>
void to_base_scaled_unit(const volatile scaled_unit<M, U>*);

} // namespace detail

Expand Down
12 changes: 6 additions & 6 deletions src/core/include/units/bits/common_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,22 @@ struct common_quantity_reference_impl<reference<D, U>, reference<D, U>> {

template<typename D, typename U1, typename U2>
struct common_quantity_reference_impl<reference<D, U1>, reference<D, U2>> {
using type = reference<D, downcast_unit<D, common_ratio(U1::ratio, U2::ratio)>>;
using type = reference<D, downcast_unit<D, common_magnitude(U1::mag, U2::mag)>>;
};

template<typename D1, typename U1, typename D2, typename U2>
requires(same_unit_reference<dimension_unit<D1>, dimension_unit<D2>>::value)
struct common_quantity_reference_impl<reference<D1, U1>, reference<D2, U2>> {
using type = reference<D1, downcast_unit<D1, common_ratio(U1::ratio, U2::ratio)>>;
using type = reference<D1, downcast_unit<D1, common_magnitude(U1::mag, U2::mag)>>;
};

template<typename D1, typename U1, typename D2, typename U2>
struct common_quantity_reference_impl<reference<D1, U1>, reference<D2, U2>> {
using dimension = conditional<is_specialization_of<D1, unknown_dimension>, D2, D1>;
static constexpr ratio r1 = D1::base_units_ratio * U1::ratio;
static constexpr ratio r2 = D2::base_units_ratio * U2::ratio;
static constexpr ratio cr = common_ratio(r1, r2);
using unit = downcast_unit<dimension, cr / dimension::base_units_ratio>;
static constexpr UNITS_MSVC_WORKAROUND(Magnitude) auto m1 = D1::base_units_ratio * U1::mag;
static constexpr UNITS_MSVC_WORKAROUND(Magnitude) auto m2 = D2::base_units_ratio * U2::mag;
static constexpr UNITS_MSVC_WORKAROUND(Magnitude) auto cm = common_magnitude(m1, m2);
using unit = downcast_unit<dimension, cm / dimension::base_units_ratio>;
using type = reference<dimension, unit>;
};

Expand Down
19 changes: 5 additions & 14 deletions src/core/include/units/bits/derived_scaled_unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#pragma once

#include <units/derived_dimension.h>
#include <units/magnitude.h>

namespace units::detail {

Expand All @@ -35,24 +36,14 @@ inline constexpr bool compatible_units<exponent_list<Es...>, Us...> = (UnitOf<Us

// derived_scaled_unit

template<Exponent E>
constexpr ratio inverse_if_negative(const ratio& r)
{
if constexpr (E::num * E::den > 0)
return r;
else
return inverse(r);
}

template<Unit... Us, typename... Es>
constexpr ratio derived_ratio(exponent_list<Es...>)
constexpr Magnitude auto derived_mag(exponent_list<Es...>)
{
return (... * inverse_if_negative<Es>(
pow<detail::abs(Es::num)>(Us::ratio / dimension_unit<typename Es::dimension>::ratio)));
return (as_magnitude<1>() * ... *
pow<ratio{Es::num, Es::den}>(Us::mag / dimension_unit<typename Es::dimension>::mag));
}

template<DerivedDimension D, Unit... Us>
using derived_scaled_unit =
scaled_unit<derived_ratio<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
using derived_scaled_unit = scaled_unit<derived_mag<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;

} // namespace units::detail
4 changes: 2 additions & 2 deletions src/core/include/units/bits/equivalent.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ struct equivalent_impl<D1, D2> :
// additionally accounts for unknown dimensions
template<Unit U1, Dimension D1, Unit U2, Dimension D2>
struct equivalent_unit :
std::disjunction<equivalent_impl<U1, U2>, std::bool_constant<U1::ratio / dimension_unit<D1>::ratio ==
U2::ratio / dimension_unit<D2>::ratio>> {};
std::disjunction<equivalent_impl<U1, U2>,
std::bool_constant<U1::mag / dimension_unit<D1>::mag == U2::mag / dimension_unit<D2>::mag>> {};

// point origins

Expand Down
10 changes: 10 additions & 0 deletions src/core/include/units/bits/external/hacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@

#endif

#if UNITS_COMP_MSVC

#define UNITS_MSVC_WORKAROUND(X)

#else

#define UNITS_MSVC_WORKAROUND(X) X

#endif


namespace std {

Expand Down
2 changes: 1 addition & 1 deletion src/core/include/units/bits/unit_text.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ constexpr auto unit_text()
}();

constexpr auto prefix_txt =
prefix_or_ratio_text<U, U::ratio / coherent_unit::ratio, symbol_text.standard().size()>();
prefix_or_ratio_text<U, as_ratio(U::mag / coherent_unit::mag), symbol_text.standard().size()>();
return prefix_txt + symbol_text;
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/core/include/units/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ namespace units {

template<typename Rep, typename Period>
struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
private:
static constexpr auto mag = as_magnitude<ratio(Period::num, Period::den)>();
public:
using dimension = isq::si::dim_time;
using unit = downcast_unit<dimension, ratio(Period::num, Period::den)>;
using unit = downcast_unit<dimension, mag>;
using rep = Rep;
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
};
Expand All @@ -44,8 +47,11 @@ struct clock_origin : point_origin<isq::si::dim_time> {};

template<typename C, typename Rep, typename Period>
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
private:
static constexpr auto mag = as_magnitude<ratio(Period::num, Period::den)>();
public:
using origin = clock_origin<C>;
using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
using unit = downcast_unit<typename origin::dimension, mag>;
using rep = Rep;
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp)
{
Expand Down Expand Up @@ -86,13 +92,13 @@ using to_std_ratio = decltype(detail::to_std_ratio_impl<R>());
template<typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_duration(const quantity<isq::si::dim_time, U, Rep>& q)
{
return std::chrono::duration<Rep, to_std_ratio<U::ratio>>(q.number());
return std::chrono::duration<Rep, to_std_ratio<as_ratio(U::mag)>>(q.number());
}

template<typename C, typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_time_point(const quantity_point<clock_origin<C>, U, Rep>& qp)
{
using ret_type = std::chrono::time_point<C, std::chrono::duration<Rep, to_std_ratio<U::ratio>>>;
using ret_type = std::chrono::time_point<C, std::chrono::duration<Rep, to_std_ratio<as_ratio(U::mag)>>>;
return ret_type(to_std_duration(qp.relative()));
}

Expand Down
3 changes: 2 additions & 1 deletion src/core/include/units/derived_dimension.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ template<typename Child, Unit U, Exponent... Es>
struct derived_dimension : downcast_dispatch<Child, typename detail::make_dimension<Es...>> {
using recipe = exponent_list<Es...>;
using coherent_unit = U;
static constexpr ratio base_units_ratio = detail::base_units_ratio(typename derived_dimension::exponents());
static constexpr UNITS_MSVC_WORKAROUND(Magnitude) auto base_units_ratio =
detail::absolute_magnitude(typename derived_dimension::exponents());
};

} // namespace units
2 changes: 1 addition & 1 deletion src/core/include/units/generic/dimensionless.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
namespace units {

struct one : derived_unit<one> {};
struct percent : named_scaled_unit<percent, "%", ratio(1, 100), one> {};
struct percent : named_scaled_unit<percent, "%", as_magnitude<ratio(1, 100)>(), one> {};

/**
* @brief Dimension one
Expand Down
Loading