39inline long find_highest_bit(
unsigned long long value)
noexcept
45 _BitScanReverse64(&index, value);
47 if (_BitScanReverse(&index,
static_cast<unsigned long>(value >> 32)) != 0) {
50 _BitScanReverse(&index,
static_cast<unsigned long>(value & 0xfffffffflu));
54#elif defined(__GNUC__) || defined(__clang__)
55 return sizeof(value) * 8 - 1 - __builtin_clzll(value);
57# error "your platform does not support find_highest_bit()"
67template <
typename B,
typename I,
unsigned int F>
68constexpr inline int fpclassify(fixed<B, I, F> x)
noexcept
70 return (x.raw_value() == 0) ? FP_ZERO : FP_NORMAL;
73template <
typename B,
typename I,
unsigned int F>
74constexpr inline bool isfinite(fixed<B, I, F>)
noexcept
79template <
typename B,
typename I,
unsigned int F>
80constexpr inline bool isinf(fixed<B, I, F>)
noexcept
85template <
typename B,
typename I,
unsigned int F>
86constexpr inline bool isnan(fixed<B, I, F>)
noexcept
91template <
typename B,
typename I,
unsigned int F>
92constexpr inline bool isnormal(fixed<B, I, F>)
noexcept
97template <
typename B,
typename I,
unsigned int F>
98constexpr inline bool signbit(fixed<B, I, F> x)
noexcept
100 return x.raw_value() < 0;
103template <
typename B,
typename I,
unsigned int F>
104constexpr inline bool isgreater(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
109template <
typename B,
typename I,
unsigned int F>
110constexpr inline bool isgreaterequal(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
115template <
typename B,
typename I,
unsigned int F>
116constexpr inline bool isless(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
121template <
typename B,
typename I,
unsigned int F>
122constexpr inline bool islessequal(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
127template <
typename B,
typename I,
unsigned int F>
128constexpr inline bool islessgreater(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
133template <
typename B,
typename I,
unsigned int F>
134constexpr inline bool isunordered(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
142template <
typename B,
typename I,
unsigned int F>
143inline fixed<B, I, F> ceil(fixed<B, I, F> x)
noexcept
145 constexpr auto FRAC = B(1) << F;
146 auto value = x.raw_value();
147 if (value > 0) value += FRAC - 1;
148 return fixed<B, I, F>::from_raw_value(value / FRAC * FRAC);
151template <
typename B,
typename I,
unsigned int F>
152inline fixed<B, I, F> floor(fixed<B, I, F> x)
noexcept
154 constexpr auto FRAC = B(1) << F;
155 auto value = x.raw_value();
156 if (value < 0) value -= FRAC - 1;
157 return fixed<B, I, F>::from_raw_value(value / FRAC * FRAC);
160template <
typename B,
typename I,
unsigned int F>
161inline fixed<B, I, F> trunc(fixed<B, I, F> x)
noexcept
163 constexpr auto FRAC = B(1) << F;
164 return fixed<B, I, F>::from_raw_value(x.raw_value() / FRAC * FRAC);
167template <
typename B,
typename I,
unsigned int F>
168inline fixed<B, I, F> round(fixed<B, I, F> x)
noexcept
170 constexpr auto FRAC = B(1) << F;
171 auto value = x.raw_value() / (FRAC / 2);
172 return fixed<B, I, F>::from_raw_value(((value / 2) + (value % 2)) * FRAC);
175template <
typename B,
typename I,
unsigned int F>
176fixed<B, I, F> nearbyint(fixed<B, I, F> x)
noexcept
179 constexpr auto FRAC = B(1) << F;
180 auto value = x.raw_value();
181 const bool is_half = std::abs(value % FRAC) == FRAC / 2;
183 value = (value / 2) + (value % 2);
184 value -= (value % 2) * is_half;
185 return fixed<B, I, F>::from_raw_value(value * FRAC);
188template <
typename B,
typename I,
unsigned int F>
189constexpr inline fixed<B, I, F> rint(fixed<B, I, F> x)
noexcept
198template <
typename B,
typename I,
unsigned int F>
199constexpr inline fixed<B, I, F> abs(fixed<B, I, F> x)
noexcept
201 return (x >= fixed<B, I, F>{0}) ? x : -x;
204template <
typename B,
typename I,
unsigned int F>
205constexpr inline fixed<B, I, F> fmod(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
208 assert(y.raw_value() != 0),
209 fixed<B, I, F>::from_raw_value(x.raw_value() % y.raw_value());
212template <
typename B,
typename I,
unsigned int F>
213constexpr inline fixed<B, I, F> remainder(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
216 assert(y.raw_value() != 0),
217 x - nearbyint(x / y) * y;
220template <
typename B,
typename I,
unsigned int F>
221inline fixed<B, I, F> remquo(fixed<B, I, F> x, fixed<B, I, F> y,
int* quo)
noexcept
223 assert(y.raw_value() != 0);
224 assert(quo !=
nullptr);
225 *quo = x.raw_value() / y.raw_value();
226 return fixed<B, I, F>::from_raw_value(x.raw_value() % y.raw_value());
233template <
typename B,
typename I,
unsigned int F,
typename C,
typename J,
unsigned int G>
234constexpr inline fixed<B, I, F> copysign(fixed<B, I, F> x, fixed<C, J, G> y)
noexcept
238 (y >= fixed<C, J, G>{0}) ? x : -x;
241template <
typename B,
typename I,
unsigned int F>
242constexpr inline fixed<B, I, F> nextafter(fixed<B, I, F> from, fixed<B, I, F> to)
noexcept
244 return from == to ? to :
245 to > from ? fixed<B, I, F>::from_raw_value(from.raw_value() + 1)
246 : fixed<B, I, F>::from_raw_value(from.raw_value() - 1);
249template <
typename B,
typename I,
unsigned int F>
250constexpr inline fixed<B, I, F> nexttoward(fixed<B, I, F> from, fixed<B, I, F> to)
noexcept
252 return nextafter(from, to);
255template <
typename B,
typename I,
unsigned int F>
256inline fixed<B, I, F> modf(fixed<B, I, F> x, fixed<B, I, F>* iptr)
noexcept
258 const auto raw = x.raw_value();
259 constexpr auto FRAC = B{1} << F;
260 *iptr = fixed<B, I, F>::from_raw_value(raw / FRAC * FRAC);
261 return fixed<B, I, F>::from_raw_value(raw % FRAC);
269template <typename B, typename I, unsigned int F, typename T, typename std::enable_if<std::is_integral<T>::value>::type* =
nullptr>
270fixed<B, I, F> pow(fixed<B, I, F> base, T exp)
noexcept
272 using Fixed = fixed<B, I, F>;
273 constexpr auto FRAC = B(1) << F;
275 if (base == Fixed(0)) {
283 for (Fixed intermediate = base; exp != 0; exp /= 2, intermediate *= intermediate)
287 result /= intermediate;
293 for (Fixed intermediate = base; exp != 0; exp /= 2, intermediate *= intermediate)
297 result *= intermediate;
304template <
typename B,
typename I,
unsigned int F>
305fixed<B, I, F> pow(fixed<B, I, F> base, fixed<B, I, F> exp)
noexcept
307 using Fixed = fixed<B, I, F>;
309 if (base == Fixed(0)) {
310 assert(exp > Fixed(0));
316 return 1 / pow(base, -exp);
319 constexpr auto FRAC = B(1) << F;
320 if (exp.raw_value() % FRAC == 0)
323 return pow(base, exp.raw_value() / FRAC);
329 assert(base > Fixed(0));
330 return exp2(log2(base) * exp);
333template <
typename B,
typename I,
unsigned int F>
334fixed<B, I, F> exp(fixed<B, I, F> x)
noexcept
336 using Fixed = fixed<B, I, F>;
340 constexpr auto FRAC = B(1) << F;
341 const B x_int = x.raw_value() / FRAC;
343 assert(x >= Fixed(0) && x < Fixed(1));
345 constexpr auto fA = Fixed::template from_fixed_point<63>( 128239257017632854ll);
346 constexpr auto fB = Fixed::template from_fixed_point<63>( 320978614890280666ll);
347 constexpr auto fC = Fixed::template from_fixed_point<63>(1571680799599592947ll);
348 constexpr auto fD = Fixed::template from_fixed_point<63>(4603349000587966862ll);
349 constexpr auto fE = Fixed::template from_fixed_point<62>(4612052447974689712ll);
350 constexpr auto fF = Fixed::template from_fixed_point<63>(9223361618412247875ll);
351 return pow(Fixed::e(), x_int) * (((((fA * x + fB) * x + fC) * x + fD) * x + fE) * x + fF);
354template <
typename B,
typename I,
unsigned int F>
355fixed<B, I, F> exp2(fixed<B, I, F> x)
noexcept
357 using Fixed = fixed<B, I, F>;
361 constexpr auto FRAC = B(1) << F;
362 const B x_int = x.raw_value() / FRAC;
364 assert(x >= Fixed(0) && x < Fixed(1));
366 constexpr auto fA = Fixed::template from_fixed_point<63>( 17491766697771214ll);
367 constexpr auto fB = Fixed::template from_fixed_point<63>( 82483038782406547ll);
368 constexpr auto fC = Fixed::template from_fixed_point<63>( 515275173969157690ll);
369 constexpr auto fD = Fixed::template from_fixed_point<63>(2214897896212987987ll);
370 constexpr auto fE = Fixed::template from_fixed_point<63>(6393224161192452326ll);
371 constexpr auto fF = Fixed::template from_fixed_point<63>(9223371050976163566ll);
372 return Fixed(1 << x_int) * (((((fA * x + fB) * x + fC) * x + fD) * x + fE) * x + fF);
375template <
typename B,
typename I,
unsigned int F>
376fixed<B, I, F> expm1(fixed<B, I, F> x)
noexcept
381template <
typename B,
typename I,
unsigned int F>
382fixed<B, I, F> log2(fixed<B, I, F> x)
noexcept
384 using Fixed = fixed<B, I, F>;
385 assert(x > Fixed(0));
388 B value = x.raw_value();
389 const long highest = detail::find_highest_bit(value);
391 value >>= (highest - F);
393 value <<= (F - highest);
395 x = Fixed::from_raw_value(value);
396 assert(x >= Fixed(1) && x < Fixed(2));
398 constexpr auto fA = Fixed::template from_fixed_point<63>( 413886001457275979ll);
399 constexpr auto fB = Fixed::template from_fixed_point<63>(-3842121857793256941ll);
400 constexpr auto fC = Fixed::template from_fixed_point<62>( 7522345947206307744ll);
401 constexpr auto fD = Fixed::template from_fixed_point<61>(-8187571043052183818ll);
402 constexpr auto fE = Fixed::template from_fixed_point<60>( 5870342889289496598ll);
403 constexpr auto fF = Fixed::template from_fixed_point<61>(-6457199832668582866ll);
404 return Fixed(highest - F) + (((((fA * x + fB) * x + fC) * x + fD) * x + fE) * x + fF);
407template <
typename B,
typename I,
unsigned int F>
408fixed<B, I, F> log(fixed<B, I, F> x)
noexcept
410 using Fixed = fixed<B, I, F>;
411 return log2(x) / log2(Fixed::e());
414template <
typename B,
typename I,
unsigned int F>
415fixed<B, I, F> log10(fixed<B, I, F> x)
noexcept
417 using Fixed = fixed<B, I, F>;
418 return log2(x) / log2(Fixed(10));
421template <
typename B,
typename I,
unsigned int F>
422fixed<B, I, F> log1p(fixed<B, I, F> x)
noexcept
427template <
typename B,
typename I,
unsigned int F>
428fixed<B, I, F> cbrt(fixed<B, I, F> x)
noexcept
430 using Fixed = fixed<B, I, F>;
440 assert(x >= Fixed(0));
446 int ofs = ((detail::find_highest_bit(x.raw_value()) + 2*F) / 3 * 3);
447 I num = I{x.raw_value()};
450 const auto do_round = [&]
452 for (; ofs >= 0; ofs -= 3)
455 const I val = (3*res*(res + 1) + 1) << ofs;
476 return Fixed::from_raw_value(
static_cast<B
>(res));
479template <
typename B,
typename I,
unsigned int F>
480fixed<B, I, F> sqrt(fixed<B, I, F> x)
noexcept
482 using Fixed = fixed<B, I, F>;
493 I num = I{x.raw_value()} << F;
497 for (I bit = I{1} << ((detail::find_highest_bit(x.raw_value()) + F) / 2 * 2); bit != 0; bit >>= 2)
499 const I val = res + bit;
514 return Fixed::from_raw_value(
static_cast<B
>(res));
517template <
typename B,
typename I,
unsigned int F>
518fixed<B, I, F> hypot(fixed<B, I, F> x, fixed<B, I, F> y)
noexcept
520 assert(x != 0 || y != 0);
521 return sqrt(x*x + y*y);
528template <
typename B,
typename I,
unsigned int F>
529fixed<B, I, F> sin(fixed<B, I, F> x)
noexcept
534 using Fixed = fixed<B, I, F>;
537 x = fmod(x, Fixed::two_pi());
538 x = x / Fixed::half_pi();
557 const Fixed x2 = x*x;
558 return sign * x * (Fixed::pi() - x2*(Fixed::two_pi() - 5 - x2*(Fixed::pi() - 3)))/2;
561template <
typename B,
typename I,
unsigned int F>
562inline fixed<B, I, F> cos(fixed<B, I, F> x)
noexcept
564 return sin(fixed<B, I, F>::half_pi() + x);
567template <
typename B,
typename I,
unsigned int F>
568inline fixed<B, I, F> tan(fixed<B, I, F> x)
noexcept
574 assert(abs(cx).raw_value() > 1);
582template <
typename B,
typename I,
unsigned int F>
583fixed<B, I, F> atan_sanitized(fixed<B, I, F> x)
noexcept
585 using Fixed = fixed<B, I, F>;
586 assert(x >= Fixed(0) && x <= Fixed(1));
588 constexpr auto fA = Fixed::template from_fixed_point<63>( 716203666280654660ll);
589 constexpr auto fB = Fixed::template from_fixed_point<63>(-2651115102768076601ll);
590 constexpr auto fC = Fixed::template from_fixed_point<63>( 9178930894564541004ll);
592 const auto xx = x * x;
593 return ((fA*xx + fB)*xx + fC)*x;
602template <
typename B,
typename I,
unsigned int F>
603fixed<B, I, F> atan_div(fixed<B, I, F> y, fixed<B, I, F> x)
noexcept
605 using Fixed = fixed<B, I, F>;
606 assert(x != Fixed(0));
613 return atan_div(-y, -x);
615 return -atan_div(-y, x);
618 return -atan_div(y, -x);
620 assert(y >= Fixed(0));
621 assert(x > Fixed(0));
624 return Fixed::half_pi() - detail::atan_sanitized(x / y);
626 return detail::atan_sanitized(y / x);
631template <
typename B,
typename I,
unsigned int F>
632fixed<B, I, F> atan(fixed<B, I, F> x)
noexcept
634 using Fixed = fixed<B, I, F>;
642 return Fixed::half_pi() - detail::atan_sanitized(Fixed(1) / x);
645 return detail::atan_sanitized(x);
648template <
typename B,
typename I,
unsigned int F>
649fixed<B, I, F> asin(fixed<B, I, F> x)
noexcept
651 using Fixed = fixed<B, I, F>;
652 assert(x >= Fixed(-1) && x <= Fixed(+1));
654 const auto yy = Fixed(1) - x * x;
657 return copysign(Fixed::half_pi(), x);
659 return detail::atan_div(x, sqrt(yy));
662template <
typename B,
typename I,
unsigned int F>
663fixed<B, I, F> acos(fixed<B, I, F> x)
noexcept
665 using Fixed = fixed<B, I, F>;
666 assert(x >= Fixed(-1) && x <= Fixed(+1));
672 const auto yy = Fixed(1) - x * x;
673 return Fixed(2)*detail::atan_div(sqrt(yy), Fixed(1) + x);
676template <
typename B,
typename I,
unsigned int F>
677fixed<B, I, F> atan2(fixed<B, I, F> y, fixed<B, I, F> x)
noexcept
679 using Fixed = fixed<B, I, F>;
681 if (x == Fixed(0) && y == Fixed(0))
687 return (y > Fixed(0)) ? Fixed::half_pi() : -Fixed::half_pi();
690 auto ret = detail::atan_div(y, x);
694 return (y >= Fixed(0)) ? ret + Fixed::pi() : ret - Fixed::pi();