xo-unit: + xquantity.rescale_ext() method

This commit is contained in:
Roland Conybeare 2024-05-24 17:54:52 -04:00
commit c1b7e94e82
6 changed files with 50 additions and 24 deletions

View file

@ -21,7 +21,7 @@ main () {
cerr << "qty3: " << qty3 << endl;
/* rescale to mm */
xquantity res = qty3.rescale(xo::qty::nu::millimeter);
xquantity res = qty3.rescale_ext(xo::qty::u::millimeter);
/* 2286mm */
cerr << "res: " << res << endl;

View file

@ -458,7 +458,7 @@ namespace xo {
/** @brief namespace for constants representing basis natural units
*
* Application code will typically use parallel scaled-unit constants
* Application code will typically use instead parallel scaled-unit constants
* (see the 'u' namespace in 'scaled_unit.hpp')
**/
namespace nu {

View file

@ -106,6 +106,8 @@ namespace xo {
///@}
};
// TODO: comparison operators
namespace detail {
/** promote natural unit to scaled unit (with unit outer scalefactors) **/
template <typename Int>
@ -134,7 +136,7 @@ namespace xo {
///@{
/** dimensionless unit; equivalent to 1 **/
constexpr auto dimensionless = detail::su_promote<std::int64_t>(nu::dimensionless);
constexpr auto dimensionless = detail::su_promote(natural_unit<std::int64_t>());
///@}

View file

@ -270,6 +270,35 @@ namespace xo {
}
}
constexpr
auto rescale_ext(const scaled_unit<Int> & unit2) const {
/* conversion factor from .unit -> unit2*/
auto rr = detail::su_ratio<ratio_int_type,
ratio_int2x_type>(unit_,
unit2.natural_unit_);
if (rr.natural_unit_.is_dimensionless()) {
/* NOTE: test for unit .outer_scale_sq values to get constexpr result with c++23
* and integer dimension powers.
*
* NOTE: we don't intend to support mixed-unit quantities.
* If we change intention, will need to take into account
* (s_scaled_unit.outer_scale_factor_, s_scaled_unit.outer_scale_sq_)
*/
repr_type r_scale
= ((((rr.outer_scale_sq_ == 1.0)
&& (unit2.outer_scale_sq_ == 1.0))
? 1.0
: ::sqrt(rr.outer_scale_sq_ / unit2.outer_scale_sq_))
* rr.outer_scale_factor_.template convert_to<repr_type>()
* this->scale_
/ unit2.outer_scale_factor_.template convert_to<repr_type>());
return xquantity(r_scale, unit2);
} else {
return xquantity(std::numeric_limits<repr_type>::quiet_NaN(), unit2);
}
}
///@}
/** @defgroup xquantity-comparison-support xquantity comparison support methods **/
@ -440,7 +469,7 @@ namespace xo {
constexpr auto
operator+ (const Quantity & x, double y)
{
return x + Quantity(y, nu::dimensionless);
return x + Quantity(y, u::dimensionless);
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -450,7 +479,7 @@ namespace xo {
constexpr auto
operator+ (double x, const Quantity & y)
{
return Quantity(x, nu::dimensionless) + y;
return Quantity(x, u::dimensionless) + y;
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -471,7 +500,7 @@ namespace xo {
constexpr auto
operator- (const Quantity & x, double y)
{
return x - Quantity(y, nu::dimensionless);
return x - Quantity(y, u::dimensionless);
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -481,7 +510,7 @@ namespace xo {
constexpr auto
operator- (double x, const Quantity & y)
{
return Quantity(x, nu::dimensionless) - y;
return Quantity(x, u::dimensionless) - y;
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -491,7 +520,7 @@ namespace xo {
constexpr auto
operator== (const Quantity & x, double y)
{
return (x == Quantity(y, nu::dimensionless));
return (x == Quantity(y, u::dimensionless));
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -501,7 +530,7 @@ namespace xo {
constexpr auto
operator== (double x, const Quantity & y)
{
return (Quantity(x, nu::dimensionless) == y);
return (Quantity(x, u::dimensionless) == y);
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -511,7 +540,7 @@ namespace xo {
constexpr auto
operator<=> (const Quantity & x, double y)
{
return Quantity::compare(x, Quantity(y, nu::dimensionless));
return Quantity::compare(x, Quantity(y, u::dimensionless));
}
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
@ -521,11 +550,11 @@ namespace xo {
constexpr auto
operator<=> (double x, const Quantity & y)
{
return Quantity::compare(Quantity(x, nu::dimensionless), y);
return Quantity::compare(Quantity(x, u::dimensionless), y);
}
namespace unit {
constexpr auto nanogram = natural_unit_qty(nu::nanogram);
namespace xu {
constexpr auto nanogram = xquantity(1.0, u::nanogram);
}
} /*namespace qty*/
} /*namespace xo*/

View file

@ -24,11 +24,6 @@ namespace xo {
template <nu64_type nu>
constexpr nu_abbrev_type nu_mpl_abbrev = nu.abbrev();
TEST_CASE("natural_unit", "[natural_unit]") {
static_assert(nu_mpl_abbrev<nu::gram> == nu::gram.abbrev());
REQUIRE(nu_mpl_abbrev<nu::gram> == nu::gram.abbrev());
} /*TEST_CASE(natural_unit)*/
TEST_CASE("natural_unit0", "[natural_unit]") {
constexpr bool c_debug_flag = false;

View file

@ -20,14 +20,14 @@ namespace xo {
constexpr su64_type su_reciprocal = su.reciprocal();
TEST_CASE("scaled_unit", "[scaled_unit]") {
static_assert(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.natural_unit_ == nu::gram.reciprocal());
REQUIRE(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.natural_unit_ == nu::gram.reciprocal());
//static_assert(u::gram.reciprocal().reciprocal() == u::gram);
//REQUIRE(u::gram.reciporcal().reciprocal() == u::gram);
static_assert(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.outer_scale_factor_ == 1);
REQUIRE(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.outer_scale_factor_ == 1);
static_assert(u::gram.reciprocal().outer_scale_factor_ == 1);
REQUIRE(u::gram.reciprocal().outer_scale_factor_ == 1);
static_assert(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.outer_scale_sq_ == 1.0);
REQUIRE(su_reciprocal<scaled_unit(nu::gram, xo::ratio::ratio(1L), 1)>.outer_scale_sq_ == 1.0);
static_assert(u::gram.reciprocal().outer_scale_sq_ == 1.0);
REQUIRE(u::gram.reciprocal().outer_scale_sq_ == 1.0);
} /*TEST_CASE(scaled_unit)*/
TEST_CASE("su_product", "[scaled_unit]") {