summaryrefslogtreecommitdiff
path: root/src/common/fixed_point.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/fixed_point.h')
-rw-r--r--src/common/fixed_point.h92
1 files changed, 42 insertions, 50 deletions
diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h
index f9adfccb0..6eb6afe2f 100644
--- a/src/common/fixed_point.h
+++ b/src/common/fixed_point.h
@@ -6,12 +6,6 @@
6 6
7#pragma once 7#pragma once
8 8
9#if __cplusplus >= 201402L
10#define CONSTEXPR14 constexpr
11#else
12#define CONSTEXPR14
13#endif
14
15#include <cstddef> // for size_t 9#include <cstddef> // for size_t
16#include <cstdint> 10#include <cstdint>
17#include <exception> 11#include <exception>
@@ -105,7 +99,7 @@ constexpr B next_to_base(N rhs) {
105struct divide_by_zero : std::exception {}; 99struct divide_by_zero : std::exception {};
106 100
107template <size_t I, size_t F> 101template <size_t I, size_t F>
108CONSTEXPR14 FixedPoint<I, F> divide( 102constexpr FixedPoint<I, F> divide(
109 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, 103 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder,
110 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 104 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) {
111 105
@@ -125,7 +119,7 @@ CONSTEXPR14 FixedPoint<I, F> divide(
125} 119}
126 120
127template <size_t I, size_t F> 121template <size_t I, size_t F>
128CONSTEXPR14 FixedPoint<I, F> divide( 122constexpr FixedPoint<I, F> divide(
129 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, 123 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder,
130 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 124 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) {
131 125
@@ -195,7 +189,7 @@ CONSTEXPR14 FixedPoint<I, F> divide(
195 189
196// this is the usual implementation of multiplication 190// this is the usual implementation of multiplication
197template <size_t I, size_t F> 191template <size_t I, size_t F>
198CONSTEXPR14 FixedPoint<I, F> multiply( 192constexpr FixedPoint<I, F> multiply(
199 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, 193 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs,
200 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 194 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) {
201 195
@@ -214,7 +208,7 @@ CONSTEXPR14 FixedPoint<I, F> multiply(
214// it is slightly slower, but is more robust since it doesn't 208// it is slightly slower, but is more robust since it doesn't
215// require and upgraded type 209// require and upgraded type
216template <size_t I, size_t F> 210template <size_t I, size_t F>
217CONSTEXPR14 FixedPoint<I, F> multiply( 211constexpr FixedPoint<I, F> multiply(
218 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, 212 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs,
219 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 213 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) {
220 214
@@ -283,7 +277,7 @@ public: // constructors
283 277
284public: // conversion 278public: // conversion
285 template <size_t I2, size_t F2> 279 template <size_t I2, size_t F2>
286 CONSTEXPR14 explicit FixedPoint(FixedPoint<I2, F2> other) { 280 constexpr explicit FixedPoint(FixedPoint<I2, F2> other) {
287 static_assert(I2 <= I && F2 <= F, "Scaling conversion can only upgrade types"); 281 static_assert(I2 <= I && F2 <= F, "Scaling conversion can only upgrade types");
288 using T = FixedPoint<I2, F2>; 282 using T = FixedPoint<I2, F2>;
289 283
@@ -352,81 +346,81 @@ public: // unary operators
352 return FixedPoint::from_base(+data_); 346 return FixedPoint::from_base(+data_);
353 } 347 }
354 348
355 CONSTEXPR14 FixedPoint& operator++() { 349 constexpr FixedPoint& operator++() {
356 data_ += one; 350 data_ += one;
357 return *this; 351 return *this;
358 } 352 }
359 353
360 CONSTEXPR14 FixedPoint& operator--() { 354 constexpr FixedPoint& operator--() {
361 data_ -= one; 355 data_ -= one;
362 return *this; 356 return *this;
363 } 357 }
364 358
365 CONSTEXPR14 FixedPoint operator++(int) { 359 constexpr FixedPoint operator++(int) {
366 FixedPoint tmp(*this); 360 FixedPoint tmp(*this);
367 data_ += one; 361 data_ += one;
368 return tmp; 362 return tmp;
369 } 363 }
370 364
371 CONSTEXPR14 FixedPoint operator--(int) { 365 constexpr FixedPoint operator--(int) {
372 FixedPoint tmp(*this); 366 FixedPoint tmp(*this);
373 data_ -= one; 367 data_ -= one;
374 return tmp; 368 return tmp;
375 } 369 }
376 370
377public: // basic math operators 371public: // basic math operators
378 CONSTEXPR14 FixedPoint& operator+=(FixedPoint n) { 372 constexpr FixedPoint& operator+=(FixedPoint n) {
379 data_ += n.data_; 373 data_ += n.data_;
380 return *this; 374 return *this;
381 } 375 }
382 376
383 CONSTEXPR14 FixedPoint& operator-=(FixedPoint n) { 377 constexpr FixedPoint& operator-=(FixedPoint n) {
384 data_ -= n.data_; 378 data_ -= n.data_;
385 return *this; 379 return *this;
386 } 380 }
387 381
388 CONSTEXPR14 FixedPoint& operator*=(FixedPoint n) { 382 constexpr FixedPoint& operator*=(FixedPoint n) {
389 return assign(detail::multiply(*this, n)); 383 return assign(detail::multiply(*this, n));
390 } 384 }
391 385
392 CONSTEXPR14 FixedPoint& operator/=(FixedPoint n) { 386 constexpr FixedPoint& operator/=(FixedPoint n) {
393 FixedPoint temp; 387 FixedPoint temp;
394 return assign(detail::divide(*this, n, temp)); 388 return assign(detail::divide(*this, n, temp));
395 } 389 }
396 390
397private: 391private:
398 CONSTEXPR14 FixedPoint& assign(FixedPoint rhs) { 392 constexpr FixedPoint& assign(FixedPoint rhs) {
399 data_ = rhs.data_; 393 data_ = rhs.data_;
400 return *this; 394 return *this;
401 } 395 }
402 396
403public: // binary math operators, effects underlying bit pattern since these 397public: // binary math operators, effects underlying bit pattern since these
404 // don't really typically make sense for non-integer values 398 // don't really typically make sense for non-integer values
405 CONSTEXPR14 FixedPoint& operator&=(FixedPoint n) { 399 constexpr FixedPoint& operator&=(FixedPoint n) {
406 data_ &= n.data_; 400 data_ &= n.data_;
407 return *this; 401 return *this;
408 } 402 }
409 403
410 CONSTEXPR14 FixedPoint& operator|=(FixedPoint n) { 404 constexpr FixedPoint& operator|=(FixedPoint n) {
411 data_ |= n.data_; 405 data_ |= n.data_;
412 return *this; 406 return *this;
413 } 407 }
414 408
415 CONSTEXPR14 FixedPoint& operator^=(FixedPoint n) { 409 constexpr FixedPoint& operator^=(FixedPoint n) {
416 data_ ^= n.data_; 410 data_ ^= n.data_;
417 return *this; 411 return *this;
418 } 412 }
419 413
420 template <class Integer, 414 template <class Integer,
421 class = typename std::enable_if<std::is_integral<Integer>::value>::type> 415 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
422 CONSTEXPR14 FixedPoint& operator>>=(Integer n) { 416 constexpr FixedPoint& operator>>=(Integer n) {
423 data_ >>= n; 417 data_ >>= n;
424 return *this; 418 return *this;
425 } 419 }
426 420
427 template <class Integer, 421 template <class Integer,
428 class = typename std::enable_if<std::is_integral<Integer>::value>::type> 422 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
429 CONSTEXPR14 FixedPoint& operator<<=(Integer n) { 423 constexpr FixedPoint& operator<<=(Integer n) {
430 data_ <<= n; 424 data_ <<= n;
431 return *this; 425 return *this;
432 } 426 }
@@ -484,7 +478,7 @@ public: // conversion to basic types
484 } 478 }
485 479
486public: 480public:
487 CONSTEXPR14 void swap(FixedPoint& rhs) { 481 constexpr void swap(FixedPoint& rhs) {
488 using std::swap; 482 using std::swap;
489 swap(data_, rhs.data_); 483 swap(data_, rhs.data_);
490 } 484 }
@@ -496,8 +490,8 @@ public:
496// if we have the same fractional portion, but differing integer portions, we trivially upgrade the 490// if we have the same fractional portion, but differing integer portions, we trivially upgrade the
497// smaller type 491// smaller type
498template <size_t I1, size_t I2, size_t F> 492template <size_t I1, size_t I2, size_t F>
499CONSTEXPR14 typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type 493constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator+(
500operator+(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 494 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
501 495
502 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 496 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type;
503 497
@@ -507,8 +501,8 @@ operator+(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
507} 501}
508 502
509template <size_t I1, size_t I2, size_t F> 503template <size_t I1, size_t I2, size_t F>
510CONSTEXPR14 typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type 504constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator-(
511operator-(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 505 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
512 506
513 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 507 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type;
514 508
@@ -518,8 +512,8 @@ operator-(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
518} 512}
519 513
520template <size_t I1, size_t I2, size_t F> 514template <size_t I1, size_t I2, size_t F>
521CONSTEXPR14 typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type 515constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator*(
522operator*(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 516 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
523 517
524 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 518 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type;
525 519
@@ -529,8 +523,8 @@ operator*(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
529} 523}
530 524
531template <size_t I1, size_t I2, size_t F> 525template <size_t I1, size_t I2, size_t F>
532CONSTEXPR14 typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type 526constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator/(
533operator/(FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 527 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
534 528
535 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 529 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type;
536 530
@@ -547,75 +541,75 @@ std::ostream& operator<<(std::ostream& os, FixedPoint<I, F> f) {
547 541
548// basic math operators 542// basic math operators
549template <size_t I, size_t F> 543template <size_t I, size_t F>
550CONSTEXPR14 FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) { 544constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) {
551 lhs += rhs; 545 lhs += rhs;
552 return lhs; 546 return lhs;
553} 547}
554template <size_t I, size_t F> 548template <size_t I, size_t F>
555CONSTEXPR14 FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) { 549constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) {
556 lhs -= rhs; 550 lhs -= rhs;
557 return lhs; 551 return lhs;
558} 552}
559template <size_t I, size_t F> 553template <size_t I, size_t F>
560CONSTEXPR14 FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) { 554constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) {
561 lhs *= rhs; 555 lhs *= rhs;
562 return lhs; 556 return lhs;
563} 557}
564template <size_t I, size_t F> 558template <size_t I, size_t F>
565CONSTEXPR14 FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) { 559constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) {
566 lhs /= rhs; 560 lhs /= rhs;
567 return lhs; 561 return lhs;
568} 562}
569 563
570template <size_t I, size_t F, class Number, 564template <size_t I, size_t F, class Number,
571 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 565 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
572CONSTEXPR14 FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { 566constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) {
573 lhs += FixedPoint<I, F>(rhs); 567 lhs += FixedPoint<I, F>(rhs);
574 return lhs; 568 return lhs;
575} 569}
576template <size_t I, size_t F, class Number, 570template <size_t I, size_t F, class Number,
577 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 571 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
578CONSTEXPR14 FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { 572constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) {
579 lhs -= FixedPoint<I, F>(rhs); 573 lhs -= FixedPoint<I, F>(rhs);
580 return lhs; 574 return lhs;
581} 575}
582template <size_t I, size_t F, class Number, 576template <size_t I, size_t F, class Number,
583 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 577 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
584CONSTEXPR14 FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { 578constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) {
585 lhs *= FixedPoint<I, F>(rhs); 579 lhs *= FixedPoint<I, F>(rhs);
586 return lhs; 580 return lhs;
587} 581}
588template <size_t I, size_t F, class Number, 582template <size_t I, size_t F, class Number,
589 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 583 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
590CONSTEXPR14 FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { 584constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) {
591 lhs /= FixedPoint<I, F>(rhs); 585 lhs /= FixedPoint<I, F>(rhs);
592 return lhs; 586 return lhs;
593} 587}
594 588
595template <size_t I, size_t F, class Number, 589template <size_t I, size_t F, class Number,
596 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 590 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
597CONSTEXPR14 FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { 591constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) {
598 FixedPoint<I, F> tmp(lhs); 592 FixedPoint<I, F> tmp(lhs);
599 tmp += rhs; 593 tmp += rhs;
600 return tmp; 594 return tmp;
601} 595}
602template <size_t I, size_t F, class Number, 596template <size_t I, size_t F, class Number,
603 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 597 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
604CONSTEXPR14 FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { 598constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) {
605 FixedPoint<I, F> tmp(lhs); 599 FixedPoint<I, F> tmp(lhs);
606 tmp -= rhs; 600 tmp -= rhs;
607 return tmp; 601 return tmp;
608} 602}
609template <size_t I, size_t F, class Number, 603template <size_t I, size_t F, class Number,
610 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 604 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
611CONSTEXPR14 FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { 605constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) {
612 FixedPoint<I, F> tmp(lhs); 606 FixedPoint<I, F> tmp(lhs);
613 tmp *= rhs; 607 tmp *= rhs;
614 return tmp; 608 return tmp;
615} 609}
616template <size_t I, size_t F, class Number, 610template <size_t I, size_t F, class Number,
617 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> 611 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
618CONSTEXPR14 FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { 612constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
619 FixedPoint<I, F> tmp(lhs); 613 FixedPoint<I, F> tmp(lhs);
620 tmp /= rhs; 614 tmp /= rhs;
621 return tmp; 615 return tmp;
@@ -624,13 +618,13 @@ CONSTEXPR14 FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
624// shift operators 618// shift operators
625template <size_t I, size_t F, class Integer, 619template <size_t I, size_t F, class Integer,
626 class = typename std::enable_if<std::is_integral<Integer>::value>::type> 620 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
627CONSTEXPR14 FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { 621constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) {
628 lhs <<= rhs; 622 lhs <<= rhs;
629 return lhs; 623 return lhs;
630} 624}
631template <size_t I, size_t F, class Integer, 625template <size_t I, size_t F, class Integer,
632 class = typename std::enable_if<std::is_integral<Integer>::value>::type> 626 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
633CONSTEXPR14 FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { 627constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) {
634 lhs >>= rhs; 628 lhs >>= rhs;
635 return lhs; 629 return lhs;
636} 630}
@@ -699,5 +693,3 @@ constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) {
699} 693}
700 694
701} // namespace Common 695} // namespace Common
702
703#undef CONSTEXPR14