forked from mpusz/mp-units
chore: unused files removed
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/base_dimension.h>
|
||||
#include <units/exponent.h>
|
||||
#include <units/magnitude.h>
|
||||
#include <units/ratio.h>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
/**
|
||||
* @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 Magnitude auto absolute_magnitude(exponent_list<Es...>)
|
||||
{
|
||||
return (magnitude<>{} * ... * pow<ratio{Es::num, Es::den}>(Es::dimension::base_unit::mag));
|
||||
}
|
||||
|
||||
} // namespace units::detail
|
@@ -1,244 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gsl/gsl-lite.hpp>
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <units/bits/math_concepts.h>
|
||||
#include <units/bits/ratio_maths.h>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
struct decimal_fp {
|
||||
double significant;
|
||||
std::intmax_t exponent;
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr decimal_fp to_decimal(double v) noexcept
|
||||
{
|
||||
UNITS_DIAGNOSTIC_PUSH
|
||||
UNITS_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
|
||||
if (v == 0) {
|
||||
return {.significant = 0.0, .exponent = 0};
|
||||
}
|
||||
UNITS_DIAGNOSTIC_POP
|
||||
|
||||
double significant = abs(v);
|
||||
std::intmax_t exponent = 0;
|
||||
|
||||
while (significant < 1) {
|
||||
significant *= 10.0;
|
||||
--exponent;
|
||||
}
|
||||
|
||||
while (significant >= 10) {
|
||||
significant /= 10.0;
|
||||
++exponent;
|
||||
}
|
||||
|
||||
if (v < 0) {
|
||||
significant = -significant;
|
||||
}
|
||||
|
||||
return {.significant = significant, .exponent = exponent};
|
||||
}
|
||||
|
||||
/* approximate natural log as https://math.stackexchange.com/a/977836
|
||||
far slower than std::log but works at compile time with similar accuracy
|
||||
*/
|
||||
[[nodiscard]] constexpr double constexpr_log(double v) noexcept
|
||||
{
|
||||
gsl_Expects(v > 0);
|
||||
|
||||
// lookup table to speed up convergence for all significant values
|
||||
// significant values of 7 and greater benefit mostly as they now converge in 5 terms compared to O(10)-O(100)
|
||||
// required without the table
|
||||
//
|
||||
// using python:
|
||||
// >>> import math
|
||||
// >>> for i in range(1, 100):
|
||||
// ... print(f"/* log({i:>2d}) = */ {math.log(i):.16f},")
|
||||
constexpr std::array<double, 99> log_table{
|
||||
/* log( 1) = */ 0.0000000000000000,
|
||||
/* log( 2) = */ 0.6931471805599453,
|
||||
/* log( 3) = */ 1.0986122886681098,
|
||||
/* log( 4) = */ 1.3862943611198906,
|
||||
/* log( 5) = */ 1.6094379124341003,
|
||||
/* log( 6) = */ 1.7917594692280550,
|
||||
/* log( 7) = */ 1.9459101490553132,
|
||||
/* log( 8) = */ 2.0794415416798357,
|
||||
/* log( 9) = */ 2.1972245773362196,
|
||||
/* log(10) = */ 2.3025850929940459,
|
||||
/* log(11) = */ 2.3978952727983707,
|
||||
/* log(12) = */ 2.4849066497880004,
|
||||
/* log(13) = */ 2.5649493574615367,
|
||||
/* log(14) = */ 2.6390573296152584,
|
||||
/* log(15) = */ 2.7080502011022101,
|
||||
/* log(16) = */ 2.7725887222397811,
|
||||
/* log(17) = */ 2.8332133440562162,
|
||||
/* log(18) = */ 2.8903717578961645,
|
||||
/* log(19) = */ 2.9444389791664403,
|
||||
/* log(20) = */ 2.9957322735539909,
|
||||
/* log(21) = */ 3.0445224377234230,
|
||||
/* log(22) = */ 3.0910424533583161,
|
||||
/* log(23) = */ 3.1354942159291497,
|
||||
/* log(24) = */ 3.1780538303479458,
|
||||
/* log(25) = */ 3.2188758248682006,
|
||||
/* log(26) = */ 3.2580965380214821,
|
||||
/* log(27) = */ 3.2958368660043291,
|
||||
/* log(28) = */ 3.3322045101752038,
|
||||
/* log(29) = */ 3.3672958299864741,
|
||||
/* log(30) = */ 3.4011973816621555,
|
||||
/* log(31) = */ 3.4339872044851463,
|
||||
/* log(32) = */ 3.4657359027997265,
|
||||
/* log(33) = */ 3.4965075614664802,
|
||||
/* log(34) = */ 3.5263605246161616,
|
||||
/* log(35) = */ 3.5553480614894135,
|
||||
/* log(36) = */ 3.5835189384561099,
|
||||
/* log(37) = */ 3.6109179126442243,
|
||||
/* log(38) = */ 3.6375861597263857,
|
||||
/* log(39) = */ 3.6635616461296463,
|
||||
/* log(40) = */ 3.6888794541139363,
|
||||
/* log(41) = */ 3.7135720667043080,
|
||||
/* log(42) = */ 3.7376696182833684,
|
||||
/* log(43) = */ 3.7612001156935624,
|
||||
/* log(44) = */ 3.7841896339182610,
|
||||
/* log(45) = */ 3.8066624897703196,
|
||||
/* log(46) = */ 3.8286413964890951,
|
||||
/* log(47) = */ 3.8501476017100584,
|
||||
/* log(48) = */ 3.8712010109078911,
|
||||
/* log(49) = */ 3.8918202981106265,
|
||||
/* log(50) = */ 3.9120230054281460,
|
||||
/* log(51) = */ 3.9318256327243257,
|
||||
/* log(52) = */ 3.9512437185814275,
|
||||
/* log(53) = */ 3.9702919135521220,
|
||||
/* log(54) = */ 3.9889840465642745,
|
||||
/* log(55) = */ 4.0073331852324712,
|
||||
/* log(56) = */ 4.0253516907351496,
|
||||
/* log(57) = */ 4.0430512678345503,
|
||||
/* log(58) = */ 4.0604430105464191,
|
||||
/* log(59) = */ 4.0775374439057197,
|
||||
/* log(60) = */ 4.0943445622221004,
|
||||
/* log(61) = */ 4.1108738641733114,
|
||||
/* log(62) = */ 4.1271343850450917,
|
||||
/* log(63) = */ 4.1431347263915326,
|
||||
/* log(64) = */ 4.1588830833596715,
|
||||
/* log(65) = */ 4.1743872698956368,
|
||||
/* log(66) = */ 4.1896547420264252,
|
||||
/* log(67) = */ 4.2046926193909657,
|
||||
/* log(68) = */ 4.2195077051761070,
|
||||
/* log(69) = */ 4.2341065045972597,
|
||||
/* log(70) = */ 4.2484952420493594,
|
||||
/* log(71) = */ 4.2626798770413155,
|
||||
/* log(72) = */ 4.2766661190160553,
|
||||
/* log(73) = */ 4.2904594411483910,
|
||||
/* log(74) = */ 4.3040650932041702,
|
||||
/* log(75) = */ 4.3174881135363101,
|
||||
/* log(76) = */ 4.3307333402863311,
|
||||
/* log(77) = */ 4.3438054218536841,
|
||||
/* log(78) = */ 4.3567088266895917,
|
||||
/* log(79) = */ 4.3694478524670215,
|
||||
/* log(80) = */ 4.3820266346738812,
|
||||
/* log(81) = */ 4.3944491546724391,
|
||||
/* log(82) = */ 4.4067192472642533,
|
||||
/* log(83) = */ 4.4188406077965983,
|
||||
/* log(84) = */ 4.4308167988433134,
|
||||
/* log(85) = */ 4.4426512564903167,
|
||||
/* log(86) = */ 4.4543472962535073,
|
||||
/* log(87) = */ 4.4659081186545837,
|
||||
/* log(88) = */ 4.4773368144782069,
|
||||
/* log(89) = */ 4.4886363697321396,
|
||||
/* log(90) = */ 4.4998096703302650,
|
||||
/* log(91) = */ 4.5108595065168497,
|
||||
/* log(92) = */ 4.5217885770490405,
|
||||
/* log(93) = */ 4.5325994931532563,
|
||||
/* log(94) = */ 4.5432947822700038,
|
||||
/* log(95) = */ 4.5538768916005408,
|
||||
/* log(96) = */ 4.5643481914678361,
|
||||
/* log(97) = */ 4.5747109785033828,
|
||||
/* log(98) = */ 4.5849674786705723,
|
||||
/* log(99) = */ 4.5951198501345898,
|
||||
};
|
||||
decimal_fp x = to_decimal(v);
|
||||
|
||||
// dividing the significant by nearest lower value in [1.0, 1.1, 1.2, ..., 9.9] will greatly improve convergence
|
||||
x.significant *= 10;
|
||||
const auto isignificant = static_cast<std::size_t>(x.significant);
|
||||
x.significant /= static_cast<double>(isignificant);
|
||||
const double result = static_cast<double>(x.exponent - 1) * log_table[9] + log_table[isignificant - 1];
|
||||
|
||||
// 1.0 <= significant < 1.1 converges rapidly
|
||||
const double y = (x.significant - 1) / (x.significant + 1);
|
||||
const double y_squared = y * y;
|
||||
double sum = 0;
|
||||
// 5 terms are needed for convergence to machine precision in the worst case scenario
|
||||
for (int k = 4; k > 0; --k) {
|
||||
sum = y_squared * (1 / (2 * static_cast<double>(k) + 1) + sum);
|
||||
}
|
||||
sum = 2 * y * (1 + sum); // k = 0 term
|
||||
return result + sum;
|
||||
}
|
||||
|
||||
/* approximate e^x as Taylor series e^x = 1 + x/1! + x^2/2! + x^3/3! +... where N is the order of the Taylor series
|
||||
use https://math.stackexchange.com/a/1988927 to improve convergence for large values
|
||||
|
||||
larger Factor values improve convergence for all values but reduce the precision
|
||||
*/
|
||||
template<std::size_t N, std::intmax_t Factor = 256>
|
||||
requires gt_zero<Factor>
|
||||
[[nodiscard]] constexpr double constexpr_exp(double v) noexcept
|
||||
{
|
||||
if constexpr (N == 0) {
|
||||
return 1.0;
|
||||
} else {
|
||||
constexpr auto coefficients = []() {
|
||||
std::array<double, N> coeffs;
|
||||
std::size_t factorial = 1;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
factorial *= i + 1;
|
||||
coeffs[i] = 1.0 / static_cast<double>(factorial);
|
||||
}
|
||||
return coeffs;
|
||||
}();
|
||||
|
||||
const double x = v / static_cast<double>(Factor);
|
||||
double result = 0;
|
||||
for (auto i = static_cast<std::intmax_t>(N - 1); i >= 0; --i) {
|
||||
result = x * (coefficients[static_cast<std::size_t>(i)] + result);
|
||||
}
|
||||
|
||||
// for factors of power of 2 this should be replaced by log2(Factor) multiplications by the compiler
|
||||
return pow_impl<Factor>(1 + result);
|
||||
}
|
||||
}
|
||||
|
||||
// default template arguments provide reasonable precision even for fairly large exponents
|
||||
// see constexpr_exp for template arguments
|
||||
template<std::size_t ExpOrder = 10, std::intmax_t Factor = 128>
|
||||
[[nodiscard]] constexpr double constexpr_pow(double v, double exponent) noexcept
|
||||
{
|
||||
const double x = exponent * constexpr_log(v);
|
||||
return constexpr_exp<ExpOrder, Factor>(x);
|
||||
}
|
||||
|
||||
} // namespace units::detail
|
@@ -1,133 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/basic_concepts.h>
|
||||
#include <units/reference.h>
|
||||
#include <units/unit.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename U>
|
||||
struct equivalent_impl : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct equivalent_impl<T, T> : std::true_type {};
|
||||
|
||||
|
||||
// units
|
||||
|
||||
template<Unit U1, Unit U2>
|
||||
struct equivalent_impl<U1, U2> : std::disjunction<std::is_base_of<U1, U2>, std::is_base_of<U2, U1>> {};
|
||||
|
||||
|
||||
// dimensions
|
||||
|
||||
template<BaseDimension D1, BaseDimension D2>
|
||||
struct equivalent_impl<D1, D2> :
|
||||
std::conjunction<std::bool_constant<D1::symbol == D2::symbol>,
|
||||
same_unit_reference<typename D1::base_unit, typename D2::base_unit>> {};
|
||||
|
||||
template<Exponent E1, Exponent E2>
|
||||
struct equivalent_exp : std::false_type {};
|
||||
|
||||
template<BaseDimension Dim1, std::intmax_t Num, std::intmax_t Den, BaseDimension Dim2>
|
||||
struct equivalent_exp<exponent<Dim1, Num, Den>, exponent<Dim2, Num, Den>> : equivalent_impl<Dim1, Dim2> {};
|
||||
|
||||
template<DerivedDimension D1, DerivedDimension D2>
|
||||
struct equivalent_derived_dim : std::false_type {};
|
||||
|
||||
template<typename... Es1, typename... Es2>
|
||||
requires(sizeof...(Es1) == sizeof...(Es2))
|
||||
struct equivalent_derived_dim<derived_dimension_base<Es1...>, derived_dimension_base<Es2...>> :
|
||||
std::conjunction<equivalent_exp<Es1, Es2>...> {};
|
||||
|
||||
template<DerivedDimension D1, DerivedDimension D2>
|
||||
struct equivalent_impl<D1, D2> :
|
||||
std::disjunction<std::is_base_of<D1, D2>, std::is_base_of<D2, D1>,
|
||||
equivalent_derived_dim<downcast_base_t<D1>, downcast_base_t<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<reference<D1, U1>::mag == reference<D2, U2>::mag>> {};
|
||||
|
||||
// point origins
|
||||
|
||||
template<typename T, typename U>
|
||||
concept EquivalentPointOrigins =
|
||||
RebindablePointOriginFor<T, typename U::dimension> && RebindablePointOriginFor<U, typename T::dimension> &&
|
||||
std::same_as<T, rebind_point_origin_dimension<U, typename T::dimension>> &&
|
||||
std::same_as<U, rebind_point_origin_dimension<T, typename U::dimension>>;
|
||||
|
||||
template<PointOrigin T, PointOrigin U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::bool_constant<EquivalentPointOrigins<T, U> &&
|
||||
equivalent_impl<typename T::dimension, typename U::dimension>::value> {};
|
||||
|
||||
|
||||
// (point) kinds
|
||||
|
||||
template<Kind T, Kind U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
|
||||
equivalent_impl<typename T::dimension, typename U::dimension>> {};
|
||||
|
||||
template<PointKind T, PointKind U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::conjunction<equivalent_impl<typename T::base_kind, typename U::base_kind>,
|
||||
equivalent_impl<typename T::origin, typename U::origin>> {};
|
||||
|
||||
|
||||
// quantities, quantity points, quantity (point) kinds
|
||||
|
||||
template<Quantity Q1, Quantity Q2>
|
||||
struct equivalent_impl<Q1, Q2> :
|
||||
std::conjunction<
|
||||
equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
|
||||
equivalent_unit<typename Q1::unit, typename Q1::dimension, typename Q2::unit, typename Q2::dimension>> {};
|
||||
|
||||
template<QuantityPoint QP1, QuantityPoint QP2>
|
||||
struct equivalent_impl<QP1, QP2> :
|
||||
std::conjunction<equivalent_impl<typename QP1::quantity_type, typename QP2::quantity_type>,
|
||||
equivalent_impl<typename QP1::origin, typename QP2::origin>> {};
|
||||
|
||||
template<QuantityKind QK1, QuantityKind QK2>
|
||||
struct equivalent_impl<QK1, QK2> :
|
||||
std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>,
|
||||
equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {};
|
||||
|
||||
template<QuantityPointKind QPK1, QuantityPointKind QPK2>
|
||||
struct equivalent_impl<QPK1, QPK2> :
|
||||
std::conjunction<equivalent_impl<typename QPK1::quantity_kind_type, typename QPK2::quantity_kind_type>,
|
||||
equivalent_impl<typename QPK1::origin, typename QPK2::origin>> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, typename U>
|
||||
inline constexpr bool equivalent = detail::equivalent_impl<T, U>::value;
|
||||
|
||||
} // namespace units
|
106
src/core/include/units/bits/external/downcasting.h
vendored
106
src/core/include/units/bits/external/downcasting.h
vendored
@@ -1,106 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef UNITS_DOWNCAST_MODE
|
||||
#if UNITS_DOWNCAST_MODE < 0 || UNITS_DOWNCAST_MODE > 2
|
||||
#error "Invalid UNITS_DOWNCAST_MODE value"
|
||||
#endif
|
||||
#else
|
||||
#define UNITS_DOWNCAST_MODE 1
|
||||
#endif
|
||||
|
||||
namespace units {
|
||||
|
||||
template<typename BaseType>
|
||||
struct downcast_base {
|
||||
using downcast_base_type = BaseType;
|
||||
UNITS_DIAGNOSTIC_PUSH
|
||||
UNITS_DIAGNOSTIC_IGNORE_NON_TEMPLATE_FRIEND
|
||||
friend auto downcast_guide(downcast_base);
|
||||
friend auto downcast_poison_pill(downcast_base);
|
||||
UNITS_DIAGNOSTIC_POP
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept Downcastable =
|
||||
requires { typename T::downcast_base_type; } && std::derived_from<T, downcast_base<typename T::downcast_base_type>>;
|
||||
|
||||
template<typename T>
|
||||
concept has_downcast_guide = requires(T t) { downcast_guide(t); };
|
||||
|
||||
template<typename T>
|
||||
concept has_downcast_poison_pill = requires(T t) { downcast_poison_pill(t); };
|
||||
|
||||
template<typename Target, Downcastable T>
|
||||
struct downcast_child : T {
|
||||
friend auto downcast_guide(typename T::downcast_base) { return std::type_identity<Target>(); }
|
||||
};
|
||||
|
||||
template<Downcastable T>
|
||||
struct downcast_poison : T {
|
||||
friend auto downcast_poison_pill(typename T::downcast_base) { return true; }
|
||||
};
|
||||
|
||||
enum class downcast_mode {
|
||||
off = 0, // no downcasting at all
|
||||
on = 1, // downcasting always forced -> compile-time errors in case of duplicated definitions
|
||||
automatic = 2 // downcasting automatically enabled if no collisions are present
|
||||
};
|
||||
|
||||
|
||||
template<typename Target, Downcastable T, downcast_mode mode = static_cast<downcast_mode>(UNITS_DOWNCAST_MODE)>
|
||||
struct downcast_dispatch :
|
||||
std::conditional_t<mode == downcast_mode::off, T,
|
||||
#ifdef UNITS_COMP_MSVC
|
||||
downcast_child<Target, T>> {
|
||||
};
|
||||
#else
|
||||
std::conditional_t<mode == downcast_mode::automatic && has_downcast_guide<T>, downcast_poison<T>,
|
||||
downcast_child<Target, T>>> {
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
constexpr auto downcast_impl()
|
||||
{
|
||||
if constexpr (has_downcast_guide<downcast_base<T>> && !has_downcast_poison_pill<downcast_base<T>>)
|
||||
return decltype(downcast_guide(std::declval<downcast_base<T>>()))();
|
||||
else
|
||||
return std::type_identity<T>();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<Downcastable T>
|
||||
using downcast = TYPENAME decltype(detail::downcast_impl<T>())::type;
|
||||
|
||||
template<Downcastable T>
|
||||
using downcast_base_t = TYPENAME T::downcast_base_type;
|
||||
|
||||
} // namespace units
|
@@ -1,143 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/dimension_op.h>
|
||||
#include <units/bits/equivalent.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
// DimensionOfT
|
||||
#if UNITS_DOWNCAST_MODE == 0
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Dim, template<typename...> typename DimTemplate>
|
||||
inline constexpr bool same_exponents_of = false;
|
||||
|
||||
template<Exponent... Es, template<typename...> typename DimTemplate>
|
||||
inline constexpr bool same_exponents_of<unknown_dimension<Es...>, DimTemplate> =
|
||||
requires {
|
||||
typename DimTemplate<unknown_dimension<Es...>, unknown_coherent_unit<Es...>, typename Es::dimension...>;
|
||||
}&& std::same_as<exponent_list<Es...>, typename DimTemplate<unknown_dimension<Es...>, unknown_coherent_unit<Es...>,
|
||||
typename Es::dimension...>::recipe>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename Dim, template<typename...> typename DimTemplate>
|
||||
concept EquivalentUnknownDimensionOfT = Dimension<Dim> && is_derived_from_specialization_of<Dim, unknown_dimension> &&
|
||||
detail::same_exponents_of<Dim, DimTemplate>;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A concept matching all dimensions matching provided dimension class template
|
||||
*
|
||||
* Satisfied by all dimensions being the instantiations derived from the provided dimension
|
||||
* class template.
|
||||
*/
|
||||
template<typename Dim, template<typename...> typename DimTemplate>
|
||||
concept DimensionOfT = Dimension<Dim> && (is_derived_from_specialization_of<Dim, DimTemplate>
|
||||
#if UNITS_DOWNCAST_MODE == 0
|
||||
|| EquivalentUnknownDimensionOfT<Dim, DimTemplate>
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief A concept matching all quantities with provided dimension class template
|
||||
*
|
||||
* Satisfied by all quantities with a dimension being the instantiation derived from
|
||||
* the provided dimension class template.
|
||||
*/
|
||||
template<typename Q, template<typename...> typename DimTemplate>
|
||||
concept QuantityOfT = Quantity<Q> && DimensionOfT<typename Q::dimension, DimTemplate>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching all quantities with provided dimension
|
||||
*
|
||||
* Satisfied by all quantities with a dimension being the instantiation derived from
|
||||
* the provided dimension type.
|
||||
*/
|
||||
template<typename Q, typename Dim>
|
||||
concept QuantityOf = Quantity<Q> && Dimension<Dim> && equivalent<typename Q::dimension, Dim>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching two equivalent quantities
|
||||
*
|
||||
* Satisfied by quantities having equivalent dimensions.
|
||||
*/
|
||||
template<typename Q1, typename Q2>
|
||||
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching all quantity points of the provided origin
|
||||
*
|
||||
* Satisfied by all quantity points with an origin equivalent to the provided one.
|
||||
*/
|
||||
template<typename QP, typename Orig>
|
||||
concept QuantityPointOf = QuantityPoint<QP> && PointOrigin<Orig> && equivalent<typename QP::origin, Orig>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching two equivalent quantity points
|
||||
*
|
||||
* Satisfied by quantity points having equivalent origins.
|
||||
*/
|
||||
template<typename QP1, typename QP2>
|
||||
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::origin>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching only quantity kinds of a specific kind.
|
||||
*
|
||||
* @tparam QK Quantity kind to verify.
|
||||
* @tparam K Kind type to use for verification.
|
||||
*/
|
||||
template<typename QK, typename K>
|
||||
concept QuantityKindOf = QuantityKind<QK> && Kind<K> && equivalent<typename QK::kind_type, K>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching two equivalent quantity kinds
|
||||
*
|
||||
* Satisfied by quantity kinds having equivalent kinds.
|
||||
*/
|
||||
template<typename QK1, typename QK2>
|
||||
concept QuantityKindEquivalentTo = QuantityKind<QK1> && QuantityKindOf<QK2, typename QK1::kind_type>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching only quantity point kinds of a specific point kind.
|
||||
*
|
||||
* @tparam QPK Quantity point kind to verify.
|
||||
* @tparam PK Point kind type to use for verification.
|
||||
*/
|
||||
template<typename QPK, typename PK>
|
||||
concept QuantityPointKindOf = QuantityPointKind<QPK> && PointKind<PK> && equivalent<typename QPK::point_kind_type, PK>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching two equivalent quantity point kinds
|
||||
*
|
||||
* Satisfied by quantity point kinds having equivalent kinds.
|
||||
*/
|
||||
template<typename QPK1, typename QPK2>
|
||||
concept QuantityPointKindEquivalentTo =
|
||||
QuantityPointKind<QPK1> && QuantityPointKindOf<QPK2, typename QPK1::point_kind_type>;
|
||||
|
||||
} // namespace units
|
Reference in New Issue
Block a user