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