xo-unit: refactor: move .hpp files to mpl/

This commit is contained in:
Roland Conybeare 2024-04-22 15:30:17 -04:00
commit 755224743e
3 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,86 @@
/** @file basis_unit.hpp **/
#include "dim_util.hpp"
#include "ratio_util.hpp"
namespace xo {
namespace unit {
/** @class basis_unit
*
* @brief A dimensionless multiple with natively-specified (i.e. at compile-time) dimension
**/
template <dim BasisDim,
native_unit_id NativeUnitId = native_unit_for_v<BasisDim>,
typename InnerScale = std::ratio<1>>
struct basis_unit {
static_assert(ratio_concept<InnerScale>);
static constexpr dim c_native_dim = BasisDim;
static constexpr basis_unit c_native_unit = NativeUnitId;
using scalefactor_type = InnerScale;
};
/** Using struct wrapper so we can partially specialize
* Specializations in [dimension.hpp], see also
**/
template <dim dim_id>
struct native_unit_abbrev_helper;
template <>
struct native_unit_abbrev_helper<dim::mass> {
static constexpr auto value = stringliteral("g");
};
template <>
struct native_unit_abbrev_helper<dim::distance> {
static constexpr auto value = stringliteral("m");
};
template <>
struct native_unit_abbrev_helper<dim::time> {
static constexpr auto value = stringliteral("s");
};
template<>
struct native_unit_abbrev_helper<dim::currency> {
static constexpr auto value = stringliteral("ccy");
};
template<>
struct native_unit_abbrev_helper<dim::price> {
static constexpr auto value = stringliteral("px");
};
template<dim BasisDim>
constexpr auto native_unit_abbrev_v = native_unit_abbrev_helper<BasisDim>::value;
namespace units {
// ----- scaled_native_unit_abbrev_helper -----
/* Require: InnerScale is ratio type; InnerScale >= 1 */
template <dim BasisDim, typename InnerScale>
struct scaled_native_unit_abbrev;
template <dim BasisDim>
struct scaled_native_unit_abbrev<BasisDim, std::ratio<1>> {
static constexpr auto value = native_unit_abbrev_v<BasisDim>;
};
template <dim BasisDim, typename InnerScale>
struct scaled_native_unit_abbrev {
/* e.g. unit of '1000 grams' will have abbrev '1000g' in absence
* of a specialization for scaled_native_unit_abbrev
*/
static constexpr auto value = stringliteral_concat(stringliteral_from_ratio<InnerScale>().value_,
native_unit_abbrev_helper<BasisDim>::value.value_);
};
template <dim BasisDim, typename InnerScale>
constexpr auto scaled_native_unit_abbrev_v = scaled_native_unit_abbrev<BasisDim, InnerScale>::value;
}
} /*namespace unit*/
} /*namespace xo*/
/** end basis_unit.hpp **/

View file

@ -0,0 +1,13 @@
/* @file ratio_concept.hpp */
#pragma once
#include <concepts>
namespace xo {
namespace unit {
template <typename Ratio>
concept ratio_concept = (std::is_signed_v<decltype(Ratio::num)>
&& std::is_signed_v<decltype(Ratio::den)>);
} /*namespace unit*/
} /*namespace xo*/

View file

@ -0,0 +1,242 @@
/* @file ratio_util.hpp */
#pragma once
#include "ratio_concept.hpp"
#include "stringliteral.hpp"
#include <ratio>
#include <numeric>
namespace xo {
namespace unit {
// ----- ratio_floor -----
template <typename Ratio>
struct ratio_floor {
using type = std::ratio<Ratio::num/Ratio::den, 1>;
};
template <typename Ratio>
using ratio_floor_t = ratio_floor<Ratio>::type;
// ----- ratio_frac -----
template <typename Ratio>
struct ratio_frac {
static_assert(ratio_concept<Ratio>);
using type = std::ratio_subtract<typename Ratio::type,
ratio_floor_t<Ratio>>::type;
};
template <typename Ratio>
using ratio_frac_t = ratio_frac<Ratio>::type;
// ----- ratio_power -----
/** ratio to an integer power
*
* ratio_power<Base,Power>::type
*
* yields a std::ratio representing Base^Power.
**/
template <typename Base, int Power, bool IsNegative = std::signbit(Power)>
struct ratio_power_aux;
template <typename Base, int Power>
struct ratio_power_aux<Base, Power, true> {
/** std::ratio representing Base^(-Power) **/
using _inverse_ratio_type = typename ratio_power_aux<Base, -Power>::type;
/** Base^(-Power)^-1 = Base^Power **/
using type = std::ratio_divide<std::ratio<1>, _inverse_ratio_type>;
static_assert(ratio_concept<type>);
};
template <typename Base>
struct ratio_power_aux<Base, 0, false> {
using type = std::ratio<1>;
};
template <typename Base>
struct ratio_power_aux<Base, 1, false> {
using type = Base;
};
template <typename Base, int Power>
struct ratio_power_aux<Base, Power, false> {
/** Base^(Power/2) **/
using _p2_ratio_type = ratio_power_aux<Base, Power/2>::type;
/** Base^(Power%2) :
* - Base^0 if Power is even
* - Base^1 if Power is odd
**/
using _x_ratio_type = ratio_power_aux<Base, Power%2>::type;
using type = std::ratio_multiply< _x_ratio_type,
std::ratio_multiply<_p2_ratio_type,
_p2_ratio_type> >;
static_assert(ratio_concept<type>);
};
// ----- ratio_power_v -----
/** compute Base^Power at compile time **/
template <typename Base, int Power>
using ratio_power_t = ratio_power_aux<Base, Power>::type;
// ----- from_ratio -----
/** Example:
* from_ratio<double, std::ratio<1,10> --> 0.1
* from_ratio<double, std::ratio<4,5> --> 0.8
**/
template <typename Repr, typename Ratio>
constexpr Repr from_ratio() {
static_assert(ratio_concept<Ratio>);
return Ratio::num / static_cast<Repr>(Ratio::den);
}
// ----- ratio2str_aux -----
/* note: using struct wrapper because partial specialization of function templates
* is not allowed
*/
template <int Num,
int Den,
bool Signbit = std::signbit(Num) ^ std::signbit(Den)>
struct ratio2str_aux;
template <int Num,
int Den>
struct ratio2str_aux<Num, Den, false> {
static constexpr auto value = stringliteral_concat("(",
stringliteral_from_int_v<Num>().value_,
"/",
stringliteral_from_int_v<Den>().value_,
")");
};
template <int Num,
int Den>
struct ratio2str_aux<Num, Den, true> {
/* note: using struct wrapper because partial specialization of function templates
* is not allowed
*/
static constexpr auto value = stringliteral_concat("-(",
stringliteral_from_int_v<-Num>().value_,
"/",
stringliteral_from_int_v<Den>().value_,
")");
};
template <int Num>
struct ratio2str_aux<Num, /*Den*/ 1, true> {
static constexpr auto value = stringliteral_concat("-",
stringliteral_from_int_v<-Num>().value_);
};
template <int Num>
struct ratio2str_aux<Num, /*Den*/ 1, false> {
static constexpr auto value = stringliteral_from_int_v<Num>();
};
template <>
struct ratio2str_aux<1, 1, false> {
static constexpr auto value = stringliteral("");
};
// ----- stringliteral_from_ratio -----
/** Example:
* - stringliteral_from_ratio<std::ratio<2,3> -> "^(2,3)"
**/
template <typename Ratio>
constexpr auto stringliteral_from_ratio() {
static_assert(ratio_concept<Ratio>);
using lowest_terms_type = Ratio::type;
return ratio2str_aux<lowest_terms_type::num, lowest_terms_type::den>().value;
};
template <typename Ratio>
constexpr char const * cstr_from_ratio() {
static_assert(ratio_concept<Ratio>);
using lowest_terms_type = Ratio::type;
return ratio2str_aux<lowest_terms_type::num, lowest_terms_type::den>().value.c_str();
};
// ----- exponent2str_aux -----
/* note: using struct wrapper because partial specialization of function templates
* is not allowed
*/
template <int Num,
int Den,
bool Signbit = std::signbit(Num) ^ std::signbit(Den)>
struct exponent2str_aux;
template <int Num,
int Den>
struct exponent2str_aux<Num, Den, false> {
static constexpr auto value = stringliteral_concat("^(",
stringliteral_from_int_v<Num>().value_,
"/",
stringliteral_from_int_v<Den>().value_,
")");
};
template <int Num,
int Den>
struct exponent2str_aux<Num, Den, true> {
/* note: using struct wrapper because partial specialization of function templates
* is not allowed
*/
static constexpr auto value = stringliteral_concat("^-(",
stringliteral_from_int_v<-Num>().value_,
"/",
stringliteral_from_int_v<Den>().value_,
")");
};
template <int Num>
struct exponent2str_aux<Num, 1, false> {
static constexpr auto value = stringliteral_concat("^",
stringliteral_from_int_v<Num>().value_);
};
template <int Num>
struct exponent2str_aux<Num, 1, true> {
/* Example:
* - exponent2str_aux<-1, 1, true> --> "^-1"
* - exponent2str_aux<-2, 1, true> --> "^-2"
*/
static constexpr auto value = stringliteral_concat("^",
stringliteral_from_int_v<Num>().value_);
};
template <>
struct exponent2str_aux<1, 1, false> {
static constexpr auto value = stringliteral("");
};
// ----- stringliteral_from_exponent -----
template <typename Ratio>
constexpr auto stringliteral_from_exponent() {
static_assert(ratio_concept<Ratio>);
return exponent2str_aux<Ratio::type::num, Ratio::type::den>().value;
};
} /*namespace unit*/
} /*namespace xo*/
/* end ratio_util.hpp */