forked from mpusz/mp-units
implementing our own (very limited) std::pow functions
integer and float treated separately perhaps not ideal, but not obvioius what would be clearly better
This commit is contained in:
committed by
Mateusz Pusz
parent
0ad78fe753
commit
23d44c1b4a
@@ -353,7 +353,11 @@ template<typename D1, typename U1, typename Rep1, typename D2, typename U2, type
|
|||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() * rhs.count());
|
using common_rep = decltype(lhs.count() * rhs.count());
|
||||||
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
||||||
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) * std::pow(10, common_rep(ratio::exp)) / common_rep(ratio::den);
|
if constexpr (treat_as_floating_point<common_rep>) {
|
||||||
|
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) * fpow10(ratio::exp) / common_rep(ratio::den);
|
||||||
|
} else {
|
||||||
|
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) * ipow10(ratio::exp) / common_rep(ratio::den);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
|
@@ -24,10 +24,40 @@
|
|||||||
|
|
||||||
#include <units/concepts.h>
|
#include <units/concepts.h>
|
||||||
#include <units/bits/dimension_op.h>
|
#include <units/bits/dimension_op.h>
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
|
constexpr std::intmax_t ipow10(std::intmax_t exp) {
|
||||||
|
// how to assert here?
|
||||||
|
// static_assert(exp >= 0, "Use fpow10() for negative exponents");
|
||||||
|
if (exp == 0) return 1;
|
||||||
|
std::intmax_t result = 1;
|
||||||
|
while (exp > 0) {
|
||||||
|
result *= 10;
|
||||||
|
--exp;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr long double fpow10(std::intmax_t exp) {
|
||||||
|
if (exp == 0) return 1.0L;
|
||||||
|
long double result = 1.0L;
|
||||||
|
if (exp < 0) {
|
||||||
|
while (exp < 0) {
|
||||||
|
result /= 10.0L;
|
||||||
|
++exp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (exp > 0) {
|
||||||
|
result *= 10.0L;
|
||||||
|
--exp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// QuantityOf
|
// QuantityOf
|
||||||
template<typename T, typename Dim>
|
template<typename T, typename Dim>
|
||||||
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>;
|
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>;
|
||||||
@@ -42,15 +72,15 @@ struct quantity_cast_impl {
|
|||||||
{
|
{
|
||||||
if constexpr (treat_as_floating_point<CRep>) {
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
||||||
static_cast<CRep>(std::pow(10, CRatio::exp)) *
|
static_cast<CRep>(fpow10(CRatio::exp)) *
|
||||||
(static_cast<CRep>(CRatio::num) /
|
(static_cast<CRep>(CRatio::num) /
|
||||||
static_cast<CRep>(CRatio::den))));
|
static_cast<CRep>(CRatio::den))));
|
||||||
} else {
|
} else {
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
||||||
static_cast<CRep>(CRatio::num) *
|
static_cast<CRep>(CRatio::num) *
|
||||||
static_cast<CRep>(CRatio::exp > 0 ? std::pow(10, CRatio::exp) : 1) /
|
static_cast<CRep>(CRatio::exp > 0 ? ipow10(CRatio::exp) : 1) /
|
||||||
(static_cast<CRep>(CRatio::den) *
|
(static_cast<CRep>(CRatio::den) *
|
||||||
static_cast<CRep>(CRatio::exp < 0 ? std::pow(10, -CRatio::exp) : 1))));
|
static_cast<CRep>(CRatio::exp < 0 ? ipow10(-CRatio::exp) : 1))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -60,7 +90,11 @@ struct quantity_cast_impl<To, CRatio, CRep, true, true> {
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
static constexpr To cast(const Q& q)
|
static constexpr To cast(const Q& q)
|
||||||
{
|
{
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(std::pow(10, CRatio::exp))));
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10(CRatio::exp))));
|
||||||
|
} else {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio::exp))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,9 +104,9 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false> {
|
|||||||
static constexpr To cast(const Q& q)
|
static constexpr To cast(const Q& q)
|
||||||
{
|
{
|
||||||
if constexpr (treat_as_floating_point<CRep>) {
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(std::pow(10, CRatio::exp)) * (CRep{1} / static_cast<CRep>(CRatio::den))));
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10(CRatio::exp)) * (CRep{1} / static_cast<CRep>(CRatio::den))));
|
||||||
} else {
|
} else {
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(std::pow(10, CRatio::exp)) / static_cast<CRep>(CRatio::den)));
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio::exp)) / static_cast<CRep>(CRatio::den)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -82,7 +116,11 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true> {
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
static constexpr To cast(const Q& q)
|
static constexpr To cast(const Q& q)
|
||||||
{
|
{
|
||||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) * static_cast<CRep>(std::pow(10, CRatio::exp))));
|
if constexpr (treat_as_floating_point<CRep>) {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) * static_cast<CRep>(fpow10(CRatio::exp))));
|
||||||
|
} else {
|
||||||
|
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) * static_cast<CRep>(ipow10(CRatio::exp))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user