21 #ifndef PLAYRHO_COMMON_FIXED_HPP
22 #define PLAYRHO_COMMON_FIXED_HPP
30 #include <type_traits>
43 template <
typename BASE_TYPE,
unsigned int FRACTION_BITS>
75 return Fixed{1, scalar_type{1}};
81 return Fixed{numeric_limits::max(), scalar_type{1}};
88 return Fixed{numeric_limits::max() - 1, scalar_type{1}};
94 return Fixed{numeric_limits::lowest(), scalar_type{1}};
101 return Fixed{numeric_limits::lowest() + 1, scalar_type{1}};
109 return Fixed{numeric_limits::lowest() + 2, scalar_type{1}};
113 template <
typename T>
116 static_assert(std::is_floating_point<T>::value,
"floating point value required");
118 return !(val <= 0 || val >= 0)?
GetNaN().m_value:
125 template <
typename T>
128 static_assert(std::is_integral<T>::value,
"integral value required");
129 static_assert(std::is_signed<T>::value,
"must be signed");
136 template <
typename T>
139 static_assert(std::is_integral<T>::value,
"integral value required");
140 static_assert(!std::is_signed<T>::value,
"must be unsigned");
141 const auto max =
static_cast<unsigned_wider_type
>(
GetMax().m_value /
ScaleFactor);
225 template <
typename BT,
unsigned int FB>
227 Fixed(
static_cast<long double>(val))
235 template <
typename T>
238 return isnan()? std::numeric_limits<T>::signaling_NaN():
246 if (
isnan() || other.isnan())
250 if (m_value < other.m_value)
254 if (m_value > other.m_value)
266 return ConvertTo<long double>();
272 return ConvertTo<double>();
278 return ConvertTo<float>();
297 return static_cast<unsigned long long>(m_value /
ScaleFactor);
304 return static_cast<unsigned long>(m_value /
ScaleFactor);
311 return static_cast<unsigned int>(m_value /
ScaleFactor);
329 return (
isnan())? *
this:
Fixed{-m_value, scalar_type{1}};
353 if (
isnan() || val.isnan()
368 else if (
isfinite() && val.isfinite())
370 const auto result = wider_type{m_value} + val.m_value;
371 if (result >
GetMax().m_value)
392 if (
isnan() || val.isnan()
407 else if (
isfinite() && val.isfinite())
409 const auto result = wider_type{m_value} - val.m_value;
410 if (result >
GetMax().m_value)
431 if (
isnan() || val.isnan())
435 else if (!
isfinite() || !val.isfinite())
437 if (m_value == 0 || val.m_value == 0)
448 const auto product = wider_type{m_value} * wider_type{val.m_value};
451 if (product != 0 && result == 0)
456 else if (result >
GetMax().m_value)
477 if (
isnan() || val.isnan())
481 else if (!
isfinite() && !val.isfinite())
489 else if (!val.isfinite())
495 const auto product = wider_type{m_value} *
ScaleFactor;
496 const auto result = product / val.m_value;
498 if (product != 0 && result == 0)
503 else if (result >
GetMax().m_value)
525 assert(!val.isnan());
527 m_value %= val.m_value;
541 return m_value ==
GetNaN().m_value;
547 return (m_value >= 0)? +1: -1;
556 using unsigned_wider_type =
typename std::make_unsigned<wider_type>::type;
565 using numeric_limits = std::numeric_limits<value_type>;
569 m_value{val * scalar.value}
578 template <
typename BT,
unsigned int FB>
585 template <
typename BT,
unsigned int FB>
592 template <
typename BT,
unsigned int FB>
599 template <
typename BT,
unsigned int FB>
606 template <
typename BT,
unsigned int FB>
609 const auto result = lhs.Compare(rhs);
615 template <
typename BT,
unsigned int FB>
618 const auto result = lhs.Compare(rhs);
623 template <
typename BT,
unsigned int FB>
631 template <
typename BT,
unsigned int FB>
639 template <
typename BT,
unsigned int FB>
647 template <
typename BT,
unsigned int FB>
655 template <
typename BT,
unsigned int FB>
666 template <
typename BT,
unsigned int FB>
673 template <
typename BT,
unsigned int FB>
679 #ifdef CONFLICT_WITH_GETINVALID
680 template <
typename BT,
unsigned int FB>
686 #endif // CONFLICT_WITH_GETINVALID
689 template <
typename BT,
unsigned int FB>
692 return os << static_cast<double>(value);
770 const auto result = lhs.Compare(rhs);
777 const auto result = lhs.Compare(rhs);
784 const auto result = lhs.Compare(rhs);
791 const auto result = lhs.Compare(rhs);
805 #ifdef PLAYRHO_INT128
820 using Fixed64 = Fixed<std::int64_t,24>;
826 return Fixed64::GetNaN();
866 return lhs.Compare(rhs) == Fixed64::CmpResult::Equal;
872 return lhs.Compare(rhs) != Fixed64::CmpResult::Equal;
877 const auto result = lhs.Compare(rhs);
878 return (result == Fixed64::CmpResult::LessThan) || (result == Fixed64::CmpResult::Equal);
883 const auto result = lhs.Compare(rhs);
884 return (result == Fixed64::CmpResult::GreaterThan) || (result == Fixed64::CmpResult::Equal);
889 const auto result = lhs.Compare(rhs);
890 return result == Fixed64::CmpResult::LessThan;
895 const auto result = lhs.Compare(rhs);
896 return result == Fixed64::CmpResult::GreaterThan;
900 template<>
struct Wider<
Fixed32> {
901 using type = Fixed64;
909 inline const char* GetTypeName<Fixed64>() noexcept
918 #endif // PLAYRHO_COMMON_FIXED_HPP