maths: convert to concepts
This commit is contained in:
parent
c5174c2817
commit
6a15651694
311
maths.hpp
311
maths.hpp
@ -6,13 +6,13 @@
|
|||||||
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MATHS_HPP
|
#pragma once
|
||||||
#define __MATHS_HPP
|
|
||||||
|
|
||||||
// DO NOT INCLUDE debug.hpp
|
// DO NOT INCLUDE debug.hpp
|
||||||
// it triggers a circular dependency; debug -> format -> maths -> debug
|
// it triggers a circular dependency; debug -> format -> maths -> debug
|
||||||
// instead, just use cassert
|
// instead, just use cassert
|
||||||
|
|
||||||
|
#include "concepts.hpp"
|
||||||
#include "types/traits.hpp"
|
#include "types/traits.hpp"
|
||||||
#include "coord/traits.hpp"
|
#include "coord/traits.hpp"
|
||||||
#include "float.hpp"
|
#include "float.hpp"
|
||||||
@ -37,9 +37,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace cruft {
|
namespace cruft {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <concepts::arithmetic T>
|
||||||
constexpr
|
constexpr T
|
||||||
std::enable_if_t<std::is_arithmetic_v<T>, T>
|
|
||||||
abs [[gnu::const]] (T t)
|
abs [[gnu::const]] (T t)
|
||||||
{
|
{
|
||||||
return t > 0 ? t : -t;
|
return t > 0 ? t : -t;
|
||||||
@ -116,47 +115,27 @@ namespace cruft {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr bool
|
||||||
std::enable_if_t<
|
|
||||||
std::is_integral<T>::value, bool
|
|
||||||
>
|
|
||||||
almost_zero (T t)
|
almost_zero (T t)
|
||||||
{
|
{
|
||||||
return t == 0;
|
if constexpr (std::is_integral_v<T>) {
|
||||||
|
return t == 0;
|
||||||
|
} else {
|
||||||
|
return almost_equal (t, T{0});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<
|
constexpr bool
|
||||||
!std::is_integral<T>::value, bool
|
|
||||||
>
|
|
||||||
almost_zero (T a)
|
|
||||||
{
|
|
||||||
return almost_equal (a, T{0});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
typename std::enable_if_t<
|
|
||||||
std::is_integral<T>::value, bool
|
|
||||||
>
|
|
||||||
exactly_zero (T t)
|
exactly_zero (T t)
|
||||||
{
|
{
|
||||||
return equal (t, T{0});
|
if constexpr (std::is_integral_v<T>) {
|
||||||
}
|
return equal (t, T{0});
|
||||||
|
} else {
|
||||||
|
return equal (t, T{0});
|
||||||
template <typename T>
|
}
|
||||||
constexpr
|
|
||||||
typename std::enable_if_t<
|
|
||||||
!std::is_integral<T>::value, bool
|
|
||||||
>
|
|
||||||
exactly_zero (T t)
|
|
||||||
{
|
|
||||||
return equal (t, T{0});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -173,11 +152,7 @@ namespace cruft {
|
|||||||
|
|
||||||
template <
|
template <
|
||||||
typename BaseT,
|
typename BaseT,
|
||||||
typename ExponentT,
|
concepts::integral ExponentT
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_integral_v<ExponentT>,
|
|
||||||
void
|
|
||||||
>
|
|
||||||
>
|
>
|
||||||
constexpr BaseT
|
constexpr BaseT
|
||||||
pow [[gnu::const]] (BaseT base, ExponentT exponent)
|
pow [[gnu::const]] (BaseT base, ExponentT exponent)
|
||||||
@ -200,10 +175,9 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <concepts::integral T>
|
||||||
constexpr
|
constexpr bool
|
||||||
std::enable_if_t<std::is_integral<T>::value, bool>
|
is_pow2 [[gnu::const]] (T value)
|
||||||
is_pow2 [[gnu::const]] (T value)
|
|
||||||
{
|
{
|
||||||
return value && !(value & (value - 1));
|
return value && !(value & (value - 1));
|
||||||
}
|
}
|
||||||
@ -211,9 +185,8 @@ namespace cruft {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Logarithms
|
// Logarithms
|
||||||
template <typename T>
|
template <concepts::integral T>
|
||||||
constexpr
|
constexpr T
|
||||||
std::enable_if_t<std::is_integral_v<T>, T>
|
|
||||||
log2 (T val)
|
log2 (T val)
|
||||||
{
|
{
|
||||||
T tally = 0;
|
T tally = 0;
|
||||||
@ -231,12 +204,9 @@ namespace cruft {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/// round T up to the nearest multiple of U
|
/// round T up to the nearest multiple of U
|
||||||
template <typename T, typename U>
|
template <concepts::integral T, concepts::integral U>
|
||||||
inline
|
inline
|
||||||
typename std::common_type<
|
std::common_type_t<T, U>
|
||||||
std::enable_if_t<std::is_integral<T>::value,T>,
|
|
||||||
std::enable_if_t<std::is_integral<U>::value,U>
|
|
||||||
>::type
|
|
||||||
round_up (T value, U size)
|
round_up (T value, U size)
|
||||||
{
|
{
|
||||||
// we perform this as two steps to avoid unnecessarily incrementing when
|
// we perform this as two steps to avoid unnecessarily incrementing when
|
||||||
@ -249,12 +219,8 @@ namespace cruft {
|
|||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
/// round T up to the nearest power-of-2
|
/// round T up to the nearest power-of-2
|
||||||
template <
|
template <concepts::integral T>
|
||||||
typename T,
|
constexpr auto
|
||||||
typename = std::enable_if_t<std::is_integral_v<T>>
|
|
||||||
>
|
|
||||||
constexpr
|
|
||||||
auto
|
|
||||||
round_pow2 (T value)
|
round_pow2 (T value)
|
||||||
{
|
{
|
||||||
--value;
|
--value;
|
||||||
@ -270,13 +236,12 @@ namespace cruft {
|
|||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
/// round T up to the nearest multiple of U and return the quotient.
|
/// round T up to the nearest multiple of U and return the quotient.
|
||||||
template <typename T, typename U>
|
template <
|
||||||
constexpr std::enable_if_t<
|
concepts::integral T,
|
||||||
std::is_integral<T>::value &&
|
concepts::integral U
|
||||||
std::is_integral<U>::value,
|
|
||||||
T
|
|
||||||
>
|
>
|
||||||
divup (const T a, const U b)
|
constexpr auto
|
||||||
|
divup (T const a, U const b)
|
||||||
{
|
{
|
||||||
return (a + b - 1) / b;
|
return (a + b - 1) / b;
|
||||||
}
|
}
|
||||||
@ -284,17 +249,16 @@ namespace cruft {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Properties
|
// Properties
|
||||||
template <typename T>
|
template <concepts::integral T>
|
||||||
constexpr
|
constexpr bool
|
||||||
std::enable_if_t<std::is_integral<T>::value, bool>
|
|
||||||
is_integer (T)
|
is_integer (T)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
template <concepts::floating_point T>
|
||||||
std::enable_if_t<std::is_floating_point<T>::value, bool>
|
constexpr bool
|
||||||
is_integer (T t)
|
is_integer (T t)
|
||||||
{
|
{
|
||||||
T i = 0;
|
T i = 0;
|
||||||
@ -303,13 +267,7 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <
|
template <concepts::integral NumericT>
|
||||||
typename NumericT,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_integral_v<NumericT>,
|
|
||||||
void
|
|
||||||
>
|
|
||||||
>
|
|
||||||
constexpr auto
|
constexpr auto
|
||||||
digits10 (NumericT v) noexcept
|
digits10 (NumericT v) noexcept
|
||||||
{
|
{
|
||||||
@ -339,12 +297,8 @@ namespace cruft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueT, typename BaseT>
|
template <concepts::integral ValueT, concepts::integral BaseT>
|
||||||
constexpr
|
constexpr int
|
||||||
std::enable_if_t<
|
|
||||||
std::is_integral_v<ValueT> && std::is_integral_v<BaseT>,
|
|
||||||
int
|
|
||||||
>
|
|
||||||
digits (ValueT value, BaseT base) noexcept
|
digits (ValueT value, BaseT base) noexcept
|
||||||
{
|
{
|
||||||
assert (base > 0);
|
assert (base > 0);
|
||||||
@ -362,10 +316,8 @@ namespace cruft {
|
|||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
/// return positive or negative unit value corresponding to the input.
|
/// return positive or negative unit value corresponding to the input.
|
||||||
template <typename T>
|
template <concepts::signed_integral T>
|
||||||
constexpr std::enable_if_t<
|
constexpr T
|
||||||
std::is_signed<T>::value && std::is_integral<T>::value, T
|
|
||||||
>
|
|
||||||
sign (T t)
|
sign (T t)
|
||||||
{
|
{
|
||||||
return t < 0 ? -1 : 1;
|
return t < 0 ? -1 : 1;
|
||||||
@ -375,10 +327,8 @@ namespace cruft {
|
|||||||
/// return positive or negative unit value corresponding to the input.
|
/// return positive or negative unit value corresponding to the input.
|
||||||
/// guaranteed to give correct results for signed zeroes, use another
|
/// guaranteed to give correct results for signed zeroes, use another
|
||||||
/// method if extreme speed is important.
|
/// method if extreme speed is important.
|
||||||
template <typename T>
|
template <concepts::floating_point T>
|
||||||
constexpr std::enable_if_t<
|
constexpr T
|
||||||
std::is_floating_point<T>::value, T
|
|
||||||
>
|
|
||||||
sign (T t)
|
sign (T t)
|
||||||
{
|
{
|
||||||
return std::signbit (t) ? -1 : 1;
|
return std::signbit (t) ? -1 : 1;
|
||||||
@ -408,32 +358,23 @@ namespace cruft {
|
|||||||
// Modulus/etc
|
// Modulus/etc
|
||||||
|
|
||||||
// namespaced wrapper for `man 3 fmod`
|
// namespaced wrapper for `man 3 fmod`
|
||||||
template <typename T>
|
template <concepts::floating_point T>
|
||||||
constexpr
|
constexpr T
|
||||||
std::enable_if_t<
|
|
||||||
std::is_floating_point<T>::value, T
|
|
||||||
>
|
|
||||||
mod (T x, T y)
|
mod (T x, T y)
|
||||||
{
|
{
|
||||||
return std::fmod (x, y);
|
return std::fmod (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <concepts::integral T>
|
||||||
constexpr
|
constexpr T
|
||||||
std::enable_if_t<
|
|
||||||
std::is_integral<T>::value, T
|
|
||||||
>
|
|
||||||
mod (T x, T y)
|
mod (T x, T y)
|
||||||
{
|
{
|
||||||
return x % y;
|
return x % y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <
|
template <concepts::floating_point ValueT>
|
||||||
typename ValueT,
|
|
||||||
typename = std::enable_if_t<std::is_floating_point_v<ValueT>>
|
|
||||||
>
|
|
||||||
ValueT
|
ValueT
|
||||||
frac (ValueT val)
|
frac (ValueT val)
|
||||||
{
|
{
|
||||||
@ -544,13 +485,11 @@ namespace cruft {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// kahan summation for long floating point sequences
|
// kahan summation for long floating point sequences
|
||||||
|
|
||||||
template <class InputT>
|
template <typename InputT>
|
||||||
std::enable_if_t<
|
requires
|
||||||
std::is_floating_point<
|
concepts::legacy_input_iterator<InputT> &&
|
||||||
typename std::iterator_traits<InputT>::value_type
|
concepts::floating_point<typename std::iterator_traits<InputT>::value_type>
|
||||||
>::value,
|
typename std::iterator_traits<InputT>::value_type
|
||||||
typename std::iterator_traits<InputT>::value_type
|
|
||||||
>
|
|
||||||
sum (InputT first, InputT last)
|
sum (InputT first, InputT last)
|
||||||
{
|
{
|
||||||
using T = typename std::iterator_traits<InputT>::value_type;
|
using T = typename std::iterator_traits<InputT>::value_type;
|
||||||
@ -576,13 +515,11 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <class InputT>
|
template <typename InputT>
|
||||||
std::enable_if_t<
|
requires
|
||||||
std::is_integral<
|
concepts::legacy_input_iterator<InputT> &&
|
||||||
typename std::iterator_traits<InputT>::value_type
|
concepts::integral<typename std::iterator_traits<InputT>::value_type>
|
||||||
>::value,
|
typename std::iterator_traits<InputT>::value_type
|
||||||
typename std::iterator_traits<InputT>::value_type
|
|
||||||
>
|
|
||||||
sum (InputT first, InputT last)
|
sum (InputT first, InputT last)
|
||||||
{
|
{
|
||||||
using T = typename std::iterator_traits<InputT>::value_type;
|
using T = typename std::iterator_traits<InputT>::value_type;
|
||||||
@ -625,37 +562,37 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename ValueT, size_t CountV>
|
template <concepts::container ContainerT>
|
||||||
const ValueT&
|
typename ContainerT::value_type const&
|
||||||
max (const std::array<ValueT,CountV> &vals)
|
max (ContainerT const &vals)
|
||||||
{
|
{
|
||||||
return *std::max_element (vals.begin (), vals.end ());
|
return *std::max_element (vals.begin (), vals.end ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueT, size_t CountV>
|
template <concepts::container ValueT>
|
||||||
ValueT&
|
typename ValueT::value_type &
|
||||||
max (std::array<ValueT,CountV> &&) = delete;
|
max (ValueT &&) = delete;
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename ValueT, size_t CountV>
|
template <concepts::container ContainerT>
|
||||||
const ValueT&
|
typename ContainerT::value_type const&
|
||||||
min (const std::array<ValueT,CountV> &vals)
|
min (ContainerT const &vals)
|
||||||
{
|
{
|
||||||
return *std::min_element (vals.begin (), vals.end ());
|
return *std::min_element (vals.begin (), vals.end ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ValueT, size_t CountV>
|
template <concepts::container ContainerT>
|
||||||
ValueT&
|
typename ContainerT::value_type&
|
||||||
min (std::array<ValueT,CountV> &&) = delete;
|
min (ContainerT &&) = delete;
|
||||||
|
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///------------------------------------------------------------------------
|
||||||
/// Returns an ordered pair where the elements come from the parameters.
|
/// Returns an ordered pair where the elements come from the parameters.
|
||||||
template <typename ValueT>
|
template <typename ValueT>
|
||||||
std::pair<ValueT,ValueT>
|
std::pair<ValueT, ValueT>
|
||||||
maxmin (ValueT a, ValueT b)
|
maxmin (ValueT a, ValueT b)
|
||||||
{
|
{
|
||||||
if (a >= b)
|
if (a >= b)
|
||||||
@ -669,13 +606,13 @@ namespace cruft {
|
|||||||
// Limiting functions
|
// Limiting functions
|
||||||
|
|
||||||
// min/max clamping
|
// min/max clamping
|
||||||
template <typename T, typename U, typename V>
|
template <
|
||||||
constexpr
|
concepts::scalar T,
|
||||||
std::enable_if_t<
|
concepts::scalar U,
|
||||||
std::is_scalar_v<T> && std::is_scalar_v<U> && std::is_scalar_v<V>,
|
concepts::scalar V
|
||||||
std::common_type_t<T,U,V>
|
|
||||||
>
|
>
|
||||||
clamp (const T val, const U lo, const V hi)
|
constexpr std::common_type_t<T,U,V>
|
||||||
|
clamp (T const val, U const lo, V const hi)
|
||||||
{
|
{
|
||||||
assert (lo <= hi);
|
assert (lo <= hi);
|
||||||
|
|
||||||
@ -699,10 +636,12 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename U, typename T>
|
template <
|
||||||
constexpr
|
concepts::numeric U,
|
||||||
std::enable_if_t<std::is_floating_point<T>::value, U>
|
concepts::numeric T
|
||||||
mix (U a, U b, T t)
|
>
|
||||||
|
constexpr U
|
||||||
|
mix (U const a, U const b, T const t)
|
||||||
{
|
{
|
||||||
// give some tolerance for floating point rounding
|
// give some tolerance for floating point rounding
|
||||||
assert (t >= -0.00001f);
|
assert (t >= -0.00001f);
|
||||||
@ -721,11 +660,11 @@ namespace cruft {
|
|||||||
/// bits have some meaning (particularly when dealing with UINTMAX)
|
/// bits have some meaning (particularly when dealing with UINTMAX)
|
||||||
|
|
||||||
// uint -> float
|
// uint -> float
|
||||||
template <typename T, typename U>
|
template <
|
||||||
constexpr
|
concepts::unsigned_integral T,
|
||||||
typename std::enable_if<
|
concepts::floating_point U
|
||||||
std::is_unsigned<T>::value && std::is_floating_point<U>::value, U
|
>
|
||||||
>::type
|
constexpr U
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
return t / static_cast<U> (std::numeric_limits<T>::max ());
|
return t / static_cast<U> (std::numeric_limits<T>::max ());
|
||||||
@ -734,11 +673,11 @@ namespace cruft {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// float -> uint
|
// float -> uint
|
||||||
template <typename T, typename U>
|
template <
|
||||||
constexpr
|
concepts::floating_point T,
|
||||||
typename std::enable_if<
|
concepts::unsigned_integral U
|
||||||
std::is_floating_point<T>::value && std::is_unsigned<U>::value, U
|
>
|
||||||
>::type
|
constexpr U
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
// Ideally std::ldexp would be involved but it complicates handing
|
// Ideally std::ldexp would be involved but it complicates handing
|
||||||
@ -769,12 +708,11 @@ namespace cruft {
|
|||||||
// float -> float, avoids identity conversion as we don't want to create
|
// float -> float, avoids identity conversion as we don't want to create
|
||||||
// ambiguous overloads
|
// ambiguous overloads
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
requires
|
||||||
typename std::enable_if<
|
concepts::floating_point<T> &&
|
||||||
std::is_floating_point<T>::value &&
|
concepts::floating_point<U> &&
|
||||||
std::is_floating_point<U>::value &&
|
(!std::is_same_v<T, U>)
|
||||||
!std::is_same<T,U>::value, U
|
constexpr U
|
||||||
>::type
|
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
return static_cast<U> (t);
|
return static_cast<U> (t);
|
||||||
@ -784,12 +722,11 @@ namespace cruft {
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// hi_uint -> lo_uint
|
// hi_uint -> lo_uint
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
requires
|
||||||
typename std::enable_if<
|
concepts::unsigned_integral<T> &&
|
||||||
std::is_unsigned<T>::value &&
|
concepts::unsigned_integral<U> &&
|
||||||
std::is_unsigned<U>::value &&
|
(sizeof (T) > sizeof (U))
|
||||||
(sizeof (T) > sizeof (U)), U
|
constexpr U
|
||||||
>::type
|
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
static_assert (sizeof (T) > sizeof (U),
|
static_assert (sizeof (T) > sizeof (U),
|
||||||
@ -805,13 +742,12 @@ namespace cruft {
|
|||||||
// lo_uint -> hi_uint
|
// lo_uint -> hi_uint
|
||||||
template <
|
template <
|
||||||
typename SrcT,
|
typename SrcT,
|
||||||
typename DstT,
|
typename DstT
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_unsigned<SrcT>::value &&
|
|
||||||
std::is_unsigned<DstT>::value &&
|
|
||||||
sizeof (SrcT) < sizeof (DstT), DstT
|
|
||||||
>
|
|
||||||
>
|
>
|
||||||
|
requires
|
||||||
|
concepts::unsigned_integral<SrcT> &&
|
||||||
|
concepts::unsigned_integral<DstT> &&
|
||||||
|
(sizeof (SrcT) < sizeof (DstT))
|
||||||
constexpr DstT
|
constexpr DstT
|
||||||
renormalise (SrcT src)
|
renormalise (SrcT src)
|
||||||
{
|
{
|
||||||
@ -852,10 +788,8 @@ namespace cruft {
|
|||||||
// identity transformation. must precede the signed cases, as they may rely
|
// identity transformation. must precede the signed cases, as they may rely
|
||||||
// on this as a side effect of casts.
|
// on this as a side effect of casts.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
requires (std::is_same_v<T, U>)
|
||||||
typename std::enable_if<
|
constexpr U
|
||||||
std::is_same<T,U>::value, U
|
|
||||||
>::type
|
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{ return t; }
|
{ return t; }
|
||||||
|
|
||||||
@ -863,13 +797,10 @@ namespace cruft {
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// anything-to-sint
|
// anything-to-sint
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
requires
|
||||||
typename std::enable_if<
|
concepts::signed_integral<U> &&
|
||||||
std::is_signed<U>::value &&
|
(!std::is_same<T,U>::value)
|
||||||
std::is_integral<U>::value &&
|
constexpr U
|
||||||
!std::is_same<T,U>::value,
|
|
||||||
U
|
|
||||||
>::type
|
|
||||||
renormalise (T t)
|
renormalise (T t)
|
||||||
{
|
{
|
||||||
using uint_t = typename std::make_unsigned<U>::type;
|
using uint_t = typename std::make_unsigned<U>::type;
|
||||||
@ -883,13 +814,10 @@ namespace cruft {
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// sint-to-anything
|
// sint-to-anything
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr
|
requires
|
||||||
typename std::enable_if<
|
concepts::signed_integral<T> &&
|
||||||
std::is_signed<T>::value &&
|
(!std::is_same<T,U>::value)
|
||||||
std::is_integral<T>::value &&
|
constexpr U
|
||||||
!std::is_same<T,U>::value,
|
|
||||||
U
|
|
||||||
>::type
|
|
||||||
renormalise (T sint)
|
renormalise (T sint)
|
||||||
{
|
{
|
||||||
using uint_t = typename std::make_unsigned<T>::type;
|
using uint_t = typename std::make_unsigned<T>::type;
|
||||||
@ -899,6 +827,3 @@ namespace cruft {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // __MATHS_HPP
|
|
||||||
|
Loading…
Reference in New Issue
Block a user