40template <
typename BaseType,
typename IntermediateType,
unsigned int FractionBits>
43 static_assert(std::is_integral<BaseType>::value,
"BaseType must be an integral type");
44 static_assert(FractionBits > 0,
"FractionBits must be greater than zero");
45 static_assert(FractionBits <=
sizeof(BaseType) * 8,
"BaseType must at least be able to contain entire fraction");
46 static_assert(FractionBits <= 62,
"Fraction may be no more than 62 bits");
47 static_assert(
sizeof(IntermediateType) >
sizeof(BaseType),
"IntermediateType must be larger than BaseType");
48 static_assert(std::is_signed<IntermediateType>::value == std::is_signed<BaseType>::value,
"IntermediateType must have same signedness as BaseType");
50 static constexpr BaseType FRACTION_MULT = BaseType(1) << FractionBits;
52 struct raw_construct_tag {};
53 constexpr inline fixed(BaseType val, raw_construct_tag) noexcept : m_value(val) {}
56 inline fixed()
noexcept {}
58 constexpr inline operator int()
const noexcept {
59 return static_cast<int>(m_value >> FractionBits);
68 inline fixed& asr(
int bits_ ) {
74 inline fixed& lsl(
int bits_ ) {
81 template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
82 constexpr inline fixed(T val) noexcept
83 : m_value(
static_cast<BaseType
>(val * FRACTION_MULT))
88 template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* =
nullptr>
89 constexpr inline explicit fixed(T val) noexcept
90 : m_value(
static_cast<BaseType
>(std::round(val * FRACTION_MULT)))
95 template <
typename B,
typename I,
unsigned int F>
100 constexpr inline explicit fixed(
int numerator_ ,
int denominator_ )
noexcept
102 m_value =
static_cast<BaseType
>( (numerator_ << FractionBits) / denominator_ );
106 template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* =
nullptr>
107 constexpr inline explicit operator T()
const noexcept
109 return static_cast<T
>(m_value) / FRACTION_MULT;
113 template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
114 constexpr inline explicit operator T()
const noexcept
116 return static_cast<T
>(m_value >> FractionBits );
121 constexpr inline BaseType raw_value()
const noexcept
125 constexpr inline BaseType set_raw_value( BaseType x_ )
noexcept
135 template <
unsigned int NumFractionBits,
typename T,
typename std::enable_if<(NumFractionBits > FractionBits)>::type* =
nullptr>
140 return fixed(
static_cast<BaseType
>(
141 value / (T(1) << (NumFractionBits - FractionBits)) +
142 (value / (T(1) << (NumFractionBits - FractionBits - 1)) % 2)),
143 raw_construct_tag{});
146 template <
unsigned int NumFractionBits,
typename T,
typename std::enable_if<(NumFractionBits <= FractionBits)>::type* =
nullptr>
147 static constexpr inline fixed from_fixed_po
int(T value) noexcept
149 return fixed(static_cast<BaseType>(
150 value * (T(1) << (FractionBits - NumFractionBits))),
151 raw_construct_tag{});
156 static constexpr inline fixed from_raw_value(BaseType value) noexcept
158 return fixed(value, raw_construct_tag{});
164 static constexpr fixed e() { return from_fixed_po
int<61>(6267931151224907085ll); }
165 static constexpr fixed pi() { return from_fixed_po
int<61>(7244019458077122842ll); }
166 static constexpr fixed half_pi() { return from_fixed_po
int<62>(7244019458077122842ll); }
167 static constexpr fixed two_pi() { return from_fixed_po
int<60>(7244019458077122842ll); }
173 constexpr inline fixed operator-() const noexcept
175 return fixed::from_raw_value(-m_value);
178 constexpr inline fixed operator+() const noexcept
180 return fixed::from_raw_value(+m_value);
183 inline fixed& operator+=(const fixed& y) noexcept
185 m_value += y.m_value;
189 template <
typename I,
typename std::enable_if<std::is_
integral<I>::value>::type* =
nullptr>
190 inline fixed& operator+=(I y)
noexcept
192 m_value += y * FRACTION_MULT;
196 inline fixed& operator-=(
const fixed& y)
noexcept
198 m_value -= y.m_value;
202 template <typename I, typename std::enable_if<std::is_integral<I>::value>::type* =
nullptr>
203 inline fixed& operator-=(I y)
noexcept
205 m_value -= y * FRACTION_MULT;
209 inline fixed& operator*=(
const fixed& y)
noexcept
214 auto value = (
static_cast<IntermediateType
>(m_value) * y.m_value) / (FRACTION_MULT / 2);
215 m_value =
static_cast<BaseType
>((value / 2) + (value % 2));
219 template <typename I, typename std::enable_if<std::is_integral<I>::value>::type* =
nullptr>
220 inline fixed& operator*=(I y)
noexcept
226 inline fixed& operator/=(
const fixed& y)
noexcept
228 assert(y.m_value != 0);
232 auto value = (
static_cast<IntermediateType
>(m_value) * FRACTION_MULT * 2) / y.m_value;
233 m_value =
static_cast<BaseType
>((value / 2) + (value % 2));
237 template <typename I, typename std::enable_if<std::is_integral<I>::value>::type* =
nullptr>
238 inline fixed& operator/=(I y)
noexcept
252template <
typename B,
typename I,
unsigned int F>
253constexpr inline fixed<B, I, F> operator+(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
255 return fixed<B, I, F>(x) += y;
258template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
259constexpr inline fixed<B, I, F> operator+(
const fixed<B, I, F>& x, T y)
noexcept
261 return fixed<B, I, F>(x) += y;
264template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
265constexpr inline fixed<B, I, F> operator+(T x,
const fixed<B, I, F>& y)
noexcept
267 return fixed<B, I, F>(y) += x;
274template <
typename B,
typename I,
unsigned int F>
275constexpr inline fixed<B, I, F> operator-(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
277 return fixed<B, I, F>(x) -= y;
280template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
281constexpr inline fixed<B, I, F> operator-(
const fixed<B, I, F>& x, T y)
noexcept
283 return fixed<B, I, F>(x) -= y;
286template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
287constexpr inline fixed<B, I, F> operator-(T x,
const fixed<B, I, F>& y)
noexcept
289 return fixed<B, I, F>(x) -= y;
296template <
typename B,
typename I,
unsigned int F>
297constexpr inline fixed<B, I, F> operator*(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
299 return fixed<B, I, F>(x) *= y;
302template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
303constexpr inline fixed<B, I, F> operator*(
const fixed<B, I, F>& x, T y)
noexcept
305 return fixed<B, I, F>(x) *= y;
308template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
309constexpr inline fixed<B, I, F> operator*(T x,
const fixed<B, I, F>& y)
noexcept
311 return fixed<B, I, F>(y) *= x;
318template <
typename B,
typename I,
unsigned int F>
319constexpr inline fixed<B, I, F> operator/(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
321 return fixed<B, I, F>(x) /= y;
324template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
325constexpr inline fixed<B, I, F> operator/(
const fixed<B, I, F>& x, T y)
noexcept
327 return fixed<B, I, F>(x) /= y;
330template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
331constexpr inline fixed<B, I, F> operator/(T x,
const fixed<B, I, F>& y)
noexcept
333 return fixed<B, I, F>(x) /= y;
340template <
typename B,
typename I,
unsigned int F>
341constexpr inline bool operator==(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
343 return x.raw_value() == y.raw_value();
346template <
typename B,
typename I,
unsigned int F>
347constexpr inline bool operator!=(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
349 return x.raw_value() != y.raw_value();
352template <
typename B,
typename I,
unsigned int F>
353constexpr inline bool operator<(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
355 return x.raw_value() < y.raw_value();
358template <
typename B,
typename I,
unsigned int F>
359constexpr inline bool operator>(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
361 return x.raw_value() > y.raw_value();
364template <
typename B,
typename I,
unsigned int F>
365constexpr inline bool operator<=(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
367 return x.raw_value() <= y.raw_value();
370template <
typename B,
typename I,
unsigned int F>
371constexpr inline bool operator>=(
const fixed<B, I, F>& x,
const fixed<B, I, F>& y)
noexcept
373 return x.raw_value() >= y.raw_value();
376template <
typename B,
typename I,
unsigned int F>
377constexpr inline bool operator>(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
379 return lhs > fixed<B, I, F>(rhs);
382template <
typename B,
typename I,
unsigned int F>
383constexpr inline bool operator>(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
385 return fixed<B, I, F>(lhs) > rhs;
389template <
typename B,
typename I,
unsigned int F>
390constexpr inline bool operator==(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
392 return lhs == fixed<B, I, F>(rhs);
395template <
typename B,
typename I,
unsigned int F>
396constexpr inline bool operator==(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
398 return fixed<B, I, F>(lhs) == rhs;
402template <
typename B,
typename I,
unsigned int F>
403constexpr inline bool operator!=(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
405 return lhs != fixed<B, I, F>(rhs);
408template <
typename B,
typename I,
unsigned int F>
409constexpr inline bool operator!=(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
411 return fixed<B, I, F>(lhs) != rhs;
415template <
typename B,
typename I,
unsigned int F>
416constexpr inline bool operator<(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
418 return lhs < fixed<B, I, F>(rhs);
421template <
typename B,
typename I,
unsigned int F>
422constexpr inline bool operator<(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
424 return fixed<B, I, F>(lhs) < rhs;
428template <
typename B,
typename I,
unsigned int F>
429constexpr inline bool operator<=(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
431 return lhs <= fixed<B, I, F>(rhs);
434template <
typename B,
typename I,
unsigned int F>
435constexpr inline bool operator<=(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
437 return fixed<B, I, F>(lhs) <= rhs;
441template <
typename B,
typename I,
unsigned int F>
442constexpr inline bool operator>=(
const fixed<B, I, F>& lhs,
int rhs)
noexcept
444 return lhs >= fixed<B, I, F>(rhs);
447template <
typename B,
typename I,
unsigned int F>
448constexpr inline bool operator>=(
int lhs,
const fixed<B, I, F>& rhs)
noexcept
450 return fixed<B, I, F>(lhs) >= rhs;
456static constexpr int max_digits10(
int bits)
460 return static_cast<int>((T{bits} * 5050445 + (T{1} << 24) - 1) >> 24);
464static constexpr int digits10(
int bits)
468 return static_cast<int>((T{bits} * 5050445) >> 24);
478template <
typename B,
typename I,
unsigned int F>
479struct hash<fpm::fixed<B,I,F>>
482 using result_type = std::size_t;
484 result_type operator()(
argument_type arg)
const noexcept(
noexcept(std::declval<std::hash<B>>()(arg.raw_value()))) {
485 return m_hash(arg.raw_value());
492template <
typename B,
typename I,
unsigned int F>
493struct numeric_limits<fpm::fixed<B,I,F>>
495 static constexpr bool is_specialized =
true;
496 static constexpr bool is_signed = std::numeric_limits<B>::is_signed;
497 static constexpr bool is_integer =
false;
498 static constexpr bool is_exact =
true;
499 static constexpr bool has_infinity =
false;
500 static constexpr bool has_quiet_NaN =
false;
501 static constexpr bool has_signaling_NaN =
false;
502 static constexpr bool has_denorm = std::denorm_absent;
503 static constexpr bool has_denorm_loss =
false;
504 static constexpr std::float_round_style round_style = std::round_to_nearest;
505 static constexpr bool is_iec_559 =
false;
506 static constexpr bool is_bounded =
true;
507 static constexpr bool is_modulo = std::numeric_limits<B>::is_modulo;
508 static constexpr int digits = std::numeric_limits<B>::digits;
514 static constexpr int digits10 = 1;
517 static constexpr int max_digits10 =
518 fpm::detail::max_digits10(std::numeric_limits<B>::digits - F) + fpm::detail::max_digits10(F);
520 static constexpr int radix = 2;
521 static constexpr int min_exponent = 1 - F;
522 static constexpr int min_exponent10 = -fpm::detail::digits10(F);
523 static constexpr int max_exponent = std::numeric_limits<B>::digits - F;
524 static constexpr int max_exponent10 = fpm::detail::digits10(std::numeric_limits<B>::digits - F);
525 static constexpr bool traps =
true;
526 static constexpr bool tinyness_before =
false;
553template <
typename B,
typename I,
unsigned int F>
554constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_specialized;
555template <
typename B,
typename I,
unsigned int F>
556constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_signed;
557template <
typename B,
typename I,
unsigned int F>
558constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_integer;
559template <
typename B,
typename I,
unsigned int F>
560constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_exact;
561template <
typename B,
typename I,
unsigned int F>
562constexpr bool numeric_limits<fpm::fixed<B,I,F>>::has_infinity;
563template <
typename B,
typename I,
unsigned int F>
564constexpr bool numeric_limits<fpm::fixed<B,I,F>>::has_quiet_NaN;
565template <
typename B,
typename I,
unsigned int F>
566constexpr bool numeric_limits<fpm::fixed<B,I,F>>::has_signaling_NaN;
567template <
typename B,
typename I,
unsigned int F>
568constexpr bool numeric_limits<fpm::fixed<B,I,F>>::has_denorm;
569template <
typename B,
typename I,
unsigned int F>
570constexpr bool numeric_limits<fpm::fixed<B,I,F>>::has_denorm_loss;
571template <
typename B,
typename I,
unsigned int F>
572constexpr std::float_round_style numeric_limits<fpm::fixed<B,I,F>>::round_style;
573template <
typename B,
typename I,
unsigned int F>
574constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_iec_559;
575template <
typename B,
typename I,
unsigned int F>
576constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_bounded;
577template <
typename B,
typename I,
unsigned int F>
578constexpr bool numeric_limits<fpm::fixed<B,I,F>>::is_modulo;
579template <
typename B,
typename I,
unsigned int F>
580constexpr int numeric_limits<fpm::fixed<B,I,F>>::digits;
581template <
typename B,
typename I,
unsigned int F>
582constexpr int numeric_limits<fpm::fixed<B,I,F>>::digits10;
583template <
typename B,
typename I,
unsigned int F>
584constexpr int numeric_limits<fpm::fixed<B,I,F>>::max_digits10;
585template <
typename B,
typename I,
unsigned int F>
586constexpr int numeric_limits<fpm::fixed<B,I,F>>::radix;
587template <
typename B,
typename I,
unsigned int F>
588constexpr int numeric_limits<fpm::fixed<B,I,F>>::min_exponent;
589template <
typename B,
typename I,
unsigned int F>
590constexpr int numeric_limits<fpm::fixed<B,I,F>>::min_exponent10;
591template <
typename B,
typename I,
unsigned int F>
592constexpr int numeric_limits<fpm::fixed<B,I,F>>::max_exponent;
593template <
typename B,
typename I,
unsigned int F>
594constexpr int numeric_limits<fpm::fixed<B,I,F>>::max_exponent10;
595template <
typename B,
typename I,
unsigned int F>
596constexpr bool numeric_limits<fpm::fixed<B,I,F>>::traps;
597template <
typename B,
typename I,
unsigned int F>
598constexpr bool numeric_limits<fpm::fixed<B,I,F>>::tinyness_before;
static constexpr fixed from_fixed_point(T value) noexcept
Definition fixed.h:136
Debug tracing macros for logging and monitoring program execution.