xo-umbrella2/xo-unit/include/xo/unit/bpu.hpp
Roland Conybeare d1fa15f248 Add 'xo-unit/' from commit 'b531e382c2'
git-subtree-dir: xo-unit
git-subtree-mainline: e9ee6992ca
git-subtree-split: b531e382c2
2025-05-10 21:29:43 -05:00

188 lines
7.4 KiB
C++

/** @file bpu.hpp
*
* Author: Roland Conybeare
**/
#pragma once
#include "basis_unit.hpp"
#include "bu_store.hpp"
namespace xo {
namespace qty {
namespace abbrev {
/** fixed-size string representation for exponent of a basis-power-unit **/
using power_abbrev_type = flatstring<16>;
/** @defgroup bpu-abbrev-helpers bpu abbrev helpers **/
///@{
/** @brief construct prefix string for unit exponent
*
* Auxiliary function for @ref bpu_abbrev
**/
constexpr power_abbrev_type
flatstring_from_exponent(const power_ratio_type & power)
{
if (power.den() == 1) {
if (power.num() == 1) {
/* for no exponent annotation for power ^1 */
return power_abbrev_type::from_chars("");
} else {
/* e.g. "^-1", "^2" */
return (power_abbrev_type::from_flatstring
(flatstring_concat(flatstring("^"),
power_abbrev_type::from_int(power.num()))));
}
} else {
/* e.g. "^1/2", "^-1/2" */
return (power_abbrev_type::from_flatstring
(flatstring_concat(flatstring("^"),
power.to_str<power_abbrev_type::fixed_capacity>())));
}
}
/** construct suffix abbreviation for a basis-power-unit **/
static constexpr bpu_abbrev_type
bpu_abbrev(dim native_dim,
const scalefactor_ratio_type & scalefactor,
const power_ratio_type & power)
{
return (bpu_abbrev_type::from_flatstring
(flatstring_concat
(bu_abbrev(basis_unit(native_dim, scalefactor)),
flatstring_from_exponent(power))));
}
///@}
}
/** @class bpu
*
* @brief represent product of a compile-time scale-factor with a rational power of a native unit
**/
template<typename Int>
struct bpu {
public:
using ratio_int_type = Int;
public:
/** @defgroup bpu-ctors bpu constructors **/
///@{
/** default constructor. creates dimensionless bpu,
* representing zero'th power of sentinel basis unit
**/
constexpr bpu() = default;
/** construct @c bpu representing exponent @p power of basis unit @p bu **/
constexpr bpu(const basis_unit & bu,
const power_ratio_type & power)
: bu_{bu},
power_{power}
{}
/** construct @c bpu representing exponent @p power of @c basis_unit(native_dim,scalefactor) **/
constexpr bpu(dim native_dim,
const scalefactor_ratio_type & scalefactor,
const power_ratio_type & power)
: bu_(native_dim, scalefactor),
power_{power}
{}
/** construct bpu representing basis unit @p bu, i.e. with unit exponent **/
static constexpr bpu<Int> unit_power(const basis_unit & bu) {
return bpu<Int>(bu, power_ratio_type(1,1));
}
///@}
/** @defgroup bpu-access-methods bpu access methods **/
///@{
/** @brief report this bpu's @ref basis_unit, e.g. @c detail::bu::minute **/
constexpr const basis_unit & bu() const { return bu_; }
/** @brief report this bpu's @ref dimension, e.g. @c dimension::time **/
constexpr dimension native_dim() const { return bu_.native_dim(); }
/** @brief report this bpu's scale factor, e.g. @c 60/1 for @c detail::bu::minute **/
constexpr const scalefactor_ratio_type & scalefactor() const { return bu_.scalefactor(); }
/** @brief report this bpu's exponent, e.g. @c 3/1 for bpu representing cubic meters **/
constexpr const power_ratio_type & power() const { return power_; }
///@}
/** @defgroup bpu-methods **/
///@{
/** abbreviation for this dimension
*
* @code
* bpu<int64_t>(dim::time,
* scalefactor_ratio_type(60,1),
* power_ratio_type(-2,1)).abbrev() => "min^-2"
* @endcode
**/
constexpr bpu_abbrev_type abbrev() const
{
return abbrev::bpu_abbrev(bu_.native_dim_,
bu_.scalefactor_,
power_);
}
/** for bpu @c x, @c x.reciprocal() represents dimension of @c 1/x
*
* Example:
* @code
* constexpr auto x = bpu<int64_t>(dim::time,
* scalefactor_ratio_type(60,1),
* power_ratio_type(1));
* x.abbrev() => "min"
* x.reciprocal().abbrev() => "min^-1"
* @endcode
**/
constexpr bpu<Int> reciprocal() const {
return bpu<Int>(bu_.native_dim(), bu_.scalefactor(), power_.negate());
}
/** construct bpu representing the same unit, but using @c Int2 to represent exponenct **/
template <typename Int2>
constexpr bpu<Int2> to_repr() const {
return bpu<Int2>(this->native_dim(),
this->scalefactor(),
ratio::ratio<Int2>(power_.num(), power_.den()));
}
///@}
public: /* need public members so that a basis_unit instance can be a non-type template parameter (a structural type) */
/** @defgroup bpu-instance-vars **/
///@{
/** this @c bpu represent a power of basis unit @c bu.
*
* Public to avoid disqualifying @c bpu as a 'structural type'.
**/
struct basis_unit bu_;
/** this unit represents basis dimension (bu) taken to this power
*
* Public to avoid disqualifying @c bpu as a 'structural type'.
**/
power_ratio_type power_ = {};
///@}
};
/** @defgroup bpu-comparison **/
///@{
/** @brief compare bpus @p x and @p y for equality
*
* Equality requires that both basis unit and power are equal
**/
template <typename Int>
inline constexpr bool
operator==(const bpu<Int> & x, const bpu<Int> & y) {
return ((x.bu() == y.bu())
&& (x.power_ == y.power_));
}
/** @brief compare bpus @p x and @p y for inequality **/
template <typename Int>
inline constexpr bool
operator!=(const bpu<Int> & x, const bpu<Int> & y) {
return ((x.bu() != y.bu())
|| (x.power_ != y.power_));
}
///@}
} /*namespace qty*/
} /*namespace xo*/
/** end bpu.hpp **/