diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/concepts.h | 8 | ||||
| -rw-r--r-- | src/common/fixed_point.h | 187 |
2 files changed, 80 insertions, 115 deletions
diff --git a/src/common/concepts.h b/src/common/concepts.h index a97555f6a..e8ce30dfe 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h | |||
| @@ -34,4 +34,12 @@ concept DerivedFrom = requires { | |||
| 34 | template <typename From, typename To> | 34 | template <typename From, typename To> |
| 35 | concept ConvertibleTo = std::is_convertible_v<From, To>; | 35 | concept ConvertibleTo = std::is_convertible_v<From, To>; |
| 36 | 36 | ||
| 37 | // No equivalents in the stdlib | ||
| 38 | |||
| 39 | template <typename T> | ||
| 40 | concept IsArithmetic = std::is_arithmetic_v<T>; | ||
| 41 | |||
| 42 | template <typename T> | ||
| 43 | concept IsIntegral = std::is_integral_v<T>; | ||
| 44 | |||
| 37 | } // namespace Common | 45 | } // namespace Common |
diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h index 6eb6afe2f..f899b0d54 100644 --- a/src/common/fixed_point.h +++ b/src/common/fixed_point.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <ostream> | 12 | #include <ostream> |
| 13 | #include <type_traits> | 13 | #include <type_traits> |
| 14 | 14 | ||
| 15 | #include <common/concepts.h> | ||
| 16 | |||
| 15 | namespace Common { | 17 | namespace Common { |
| 16 | 18 | ||
| 17 | template <size_t I, size_t F> | 19 | template <size_t I, size_t F> |
| @@ -50,8 +52,8 @@ struct type_from_size<64> { | |||
| 50 | static constexpr size_t size = 64; | 52 | static constexpr size_t size = 64; |
| 51 | 53 | ||
| 52 | using value_type = int64_t; | 54 | using value_type = int64_t; |
| 53 | using unsigned_type = std::make_unsigned<value_type>::type; | 55 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 54 | using signed_type = std::make_signed<value_type>::type; | 56 | using signed_type = std::make_signed_t<value_type>; |
| 55 | using next_size = type_from_size<128>; | 57 | using next_size = type_from_size<128>; |
| 56 | }; | 58 | }; |
| 57 | 59 | ||
| @@ -61,8 +63,8 @@ struct type_from_size<32> { | |||
| 61 | static constexpr size_t size = 32; | 63 | static constexpr size_t size = 32; |
| 62 | 64 | ||
| 63 | using value_type = int32_t; | 65 | using value_type = int32_t; |
| 64 | using unsigned_type = std::make_unsigned<value_type>::type; | 66 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 65 | using signed_type = std::make_signed<value_type>::type; | 67 | using signed_type = std::make_signed_t<value_type>; |
| 66 | using next_size = type_from_size<64>; | 68 | using next_size = type_from_size<64>; |
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| @@ -72,8 +74,8 @@ struct type_from_size<16> { | |||
| 72 | static constexpr size_t size = 16; | 74 | static constexpr size_t size = 16; |
| 73 | 75 | ||
| 74 | using value_type = int16_t; | 76 | using value_type = int16_t; |
| 75 | using unsigned_type = std::make_unsigned<value_type>::type; | 77 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 76 | using signed_type = std::make_signed<value_type>::type; | 78 | using signed_type = std::make_signed_t<value_type>; |
| 77 | using next_size = type_from_size<32>; | 79 | using next_size = type_from_size<32>; |
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| @@ -83,8 +85,8 @@ struct type_from_size<8> { | |||
| 83 | static constexpr size_t size = 8; | 85 | static constexpr size_t size = 8; |
| 84 | 86 | ||
| 85 | using value_type = int8_t; | 87 | using value_type = int8_t; |
| 86 | using unsigned_type = std::make_unsigned<value_type>::type; | 88 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 87 | using signed_type = std::make_signed<value_type>::type; | 89 | using signed_type = std::make_signed_t<value_type>; |
| 88 | using next_size = type_from_size<16>; | 90 | using next_size = type_from_size<16>; |
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| @@ -101,7 +103,7 @@ struct divide_by_zero : std::exception {}; | |||
| 101 | template <size_t I, size_t F> | 103 | template <size_t I, size_t F> |
| 102 | constexpr FixedPoint<I, F> divide( | 104 | constexpr FixedPoint<I, F> divide( |
| 103 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, | 105 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, |
| 104 | typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 106 | std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 105 | 107 | ||
| 106 | using next_type = typename FixedPoint<I, F>::next_type; | 108 | using next_type = typename FixedPoint<I, F>::next_type; |
| 107 | using base_type = typename FixedPoint<I, F>::base_type; | 109 | using base_type = typename FixedPoint<I, F>::base_type; |
| @@ -121,7 +123,7 @@ constexpr FixedPoint<I, F> divide( | |||
| 121 | template <size_t I, size_t F> | 123 | template <size_t I, size_t F> |
| 122 | constexpr FixedPoint<I, F> divide( | 124 | constexpr FixedPoint<I, F> divide( |
| 123 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, | 125 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, |
| 124 | typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 126 | std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 125 | 127 | ||
| 126 | using unsigned_type = typename FixedPoint<I, F>::unsigned_type; | 128 | using unsigned_type = typename FixedPoint<I, F>::unsigned_type; |
| 127 | 129 | ||
| @@ -191,7 +193,7 @@ constexpr FixedPoint<I, F> divide( | |||
| 191 | template <size_t I, size_t F> | 193 | template <size_t I, size_t F> |
| 192 | constexpr FixedPoint<I, F> multiply( | 194 | constexpr FixedPoint<I, F> multiply( |
| 193 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, | 195 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, |
| 194 | typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 196 | std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 195 | 197 | ||
| 196 | using next_type = typename FixedPoint<I, F>::next_type; | 198 | using next_type = typename FixedPoint<I, F>::next_type; |
| 197 | using base_type = typename FixedPoint<I, F>::base_type; | 199 | using base_type = typename FixedPoint<I, F>::base_type; |
| @@ -210,7 +212,7 @@ constexpr FixedPoint<I, F> multiply( | |||
| 210 | template <size_t I, size_t F> | 212 | template <size_t I, size_t F> |
| 211 | constexpr FixedPoint<I, F> multiply( | 213 | constexpr FixedPoint<I, F> multiply( |
| 212 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, | 214 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, |
| 213 | typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 215 | std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 214 | 216 | ||
| 215 | using base_type = typename FixedPoint<I, F>::base_type; | 217 | using base_type = typename FixedPoint<I, F>::base_type; |
| 216 | 218 | ||
| @@ -265,15 +267,16 @@ public: | |||
| 265 | static constexpr base_type one = base_type(1) << fractional_bits; | 267 | static constexpr base_type one = base_type(1) << fractional_bits; |
| 266 | 268 | ||
| 267 | public: // constructors | 269 | public: // constructors |
| 268 | FixedPoint() = default; | 270 | constexpr FixedPoint() = default; |
| 269 | FixedPoint(const FixedPoint&) = default; | 271 | |
| 270 | FixedPoint(FixedPoint&&) = default; | 272 | constexpr FixedPoint(const FixedPoint&) = default; |
| 271 | FixedPoint& operator=(const FixedPoint&) = default; | 273 | constexpr FixedPoint& operator=(const FixedPoint&) = default; |
| 272 | 274 | ||
| 273 | template <class Number> | 275 | constexpr FixedPoint(FixedPoint&&) noexcept = default; |
| 274 | constexpr FixedPoint( | 276 | constexpr FixedPoint& operator=(FixedPoint&&) noexcept = default; |
| 275 | Number n, typename std::enable_if<std::is_arithmetic<Number>::value>::type* = nullptr) | 277 | |
| 276 | : data_(static_cast<base_type>(n * one)) {} | 278 | template <IsArithmetic Number> |
| 279 | constexpr FixedPoint(Number n) : data_(static_cast<base_type>(n * one)) {} | ||
| 277 | 280 | ||
| 278 | public: // conversion | 281 | public: // conversion |
| 279 | template <size_t I2, size_t F2> | 282 | template <size_t I2, size_t F2> |
| @@ -301,36 +304,14 @@ public: | |||
| 301 | } | 304 | } |
| 302 | 305 | ||
| 303 | public: // comparison operators | 306 | public: // comparison operators |
| 304 | constexpr bool operator==(FixedPoint rhs) const { | 307 | friend constexpr auto operator<=>(FixedPoint lhs, FixedPoint rhs) = default; |
| 305 | return data_ == rhs.data_; | ||
| 306 | } | ||
| 307 | |||
| 308 | constexpr bool operator!=(FixedPoint rhs) const { | ||
| 309 | return data_ != rhs.data_; | ||
| 310 | } | ||
| 311 | |||
| 312 | constexpr bool operator<(FixedPoint rhs) const { | ||
| 313 | return data_ < rhs.data_; | ||
| 314 | } | ||
| 315 | |||
| 316 | constexpr bool operator>(FixedPoint rhs) const { | ||
| 317 | return data_ > rhs.data_; | ||
| 318 | } | ||
| 319 | |||
| 320 | constexpr bool operator<=(FixedPoint rhs) const { | ||
| 321 | return data_ <= rhs.data_; | ||
| 322 | } | ||
| 323 | |||
| 324 | constexpr bool operator>=(FixedPoint rhs) const { | ||
| 325 | return data_ >= rhs.data_; | ||
| 326 | } | ||
| 327 | 308 | ||
| 328 | public: // unary operators | 309 | public: // unary operators |
| 329 | constexpr bool operator!() const { | 310 | [[nodiscard]] constexpr bool operator!() const { |
| 330 | return !data_; | 311 | return !data_; |
| 331 | } | 312 | } |
| 332 | 313 | ||
| 333 | constexpr FixedPoint operator~() const { | 314 | [[nodiscard]] constexpr FixedPoint operator~() const { |
| 334 | // NOTE(eteran): this will often appear to "just negate" the value | 315 | // NOTE(eteran): this will often appear to "just negate" the value |
| 335 | // that is not an error, it is because -x == (~x+1) | 316 | // that is not an error, it is because -x == (~x+1) |
| 336 | // and that "+1" is adding an infinitesimally small fraction to the | 317 | // and that "+1" is adding an infinitesimally small fraction to the |
| @@ -338,11 +319,11 @@ public: // unary operators | |||
| 338 | return FixedPoint::from_base(~data_); | 319 | return FixedPoint::from_base(~data_); |
| 339 | } | 320 | } |
| 340 | 321 | ||
| 341 | constexpr FixedPoint operator-() const { | 322 | [[nodiscard]] constexpr FixedPoint operator-() const { |
| 342 | return FixedPoint::from_base(-data_); | 323 | return FixedPoint::from_base(-data_); |
| 343 | } | 324 | } |
| 344 | 325 | ||
| 345 | constexpr FixedPoint operator+() const { | 326 | [[nodiscard]] constexpr FixedPoint operator+() const { |
| 346 | return FixedPoint::from_base(+data_); | 327 | return FixedPoint::from_base(+data_); |
| 347 | } | 328 | } |
| 348 | 329 | ||
| @@ -411,15 +392,13 @@ public: // binary math operators, effects underlying bit pattern since these | |||
| 411 | return *this; | 392 | return *this; |
| 412 | } | 393 | } |
| 413 | 394 | ||
| 414 | template <class Integer, | 395 | template <IsIntegral Integer> |
| 415 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 416 | constexpr FixedPoint& operator>>=(Integer n) { | 396 | constexpr FixedPoint& operator>>=(Integer n) { |
| 417 | data_ >>= n; | 397 | data_ >>= n; |
| 418 | return *this; | 398 | return *this; |
| 419 | } | 399 | } |
| 420 | 400 | ||
| 421 | template <class Integer, | 401 | template <IsIntegral Integer> |
| 422 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 423 | constexpr FixedPoint& operator<<=(Integer n) { | 402 | constexpr FixedPoint& operator<<=(Integer n) { |
| 424 | data_ <<= n; | 403 | data_ <<= n; |
| 425 | return *this; | 404 | return *this; |
| @@ -430,42 +409,42 @@ public: // conversion to basic types | |||
| 430 | data_ += (data_ & fractional_mask) >> 1; | 409 | data_ += (data_ & fractional_mask) >> 1; |
| 431 | } | 410 | } |
| 432 | 411 | ||
| 433 | constexpr int to_int() { | 412 | [[nodiscard]] constexpr int to_int() { |
| 434 | round_up(); | 413 | round_up(); |
| 435 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); | 414 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); |
| 436 | } | 415 | } |
| 437 | 416 | ||
| 438 | constexpr unsigned int to_uint() const { | 417 | [[nodiscard]] constexpr unsigned int to_uint() { |
| 439 | round_up(); | 418 | round_up(); |
| 440 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); | 419 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); |
| 441 | } | 420 | } |
| 442 | 421 | ||
| 443 | constexpr int64_t to_long() { | 422 | [[nodiscard]] constexpr int64_t to_long() { |
| 444 | round_up(); | 423 | round_up(); |
| 445 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); | 424 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); |
| 446 | } | 425 | } |
| 447 | 426 | ||
| 448 | constexpr int to_int_floor() const { | 427 | [[nodiscard]] constexpr int to_int_floor() const { |
| 449 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); | 428 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); |
| 450 | } | 429 | } |
| 451 | 430 | ||
| 452 | constexpr int64_t to_long_floor() { | 431 | [[nodiscard]] constexpr int64_t to_long_floor() const { |
| 453 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); | 432 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); |
| 454 | } | 433 | } |
| 455 | 434 | ||
| 456 | constexpr unsigned int to_uint_floor() const { | 435 | [[nodiscard]] constexpr unsigned int to_uint_floor() const { |
| 457 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); | 436 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); |
| 458 | } | 437 | } |
| 459 | 438 | ||
| 460 | constexpr float to_float() const { | 439 | [[nodiscard]] constexpr float to_float() const { |
| 461 | return static_cast<float>(data_) / FixedPoint::one; | 440 | return static_cast<float>(data_) / FixedPoint::one; |
| 462 | } | 441 | } |
| 463 | 442 | ||
| 464 | constexpr double to_double() const { | 443 | [[nodiscard]] constexpr double to_double() const { |
| 465 | return static_cast<double>(data_) / FixedPoint::one; | 444 | return static_cast<double>(data_) / FixedPoint::one; |
| 466 | } | 445 | } |
| 467 | 446 | ||
| 468 | constexpr base_type to_raw() const { | 447 | [[nodiscard]] constexpr base_type to_raw() const { |
| 469 | return data_; | 448 | return data_; |
| 470 | } | 449 | } |
| 471 | 450 | ||
| @@ -473,27 +452,27 @@ public: // conversion to basic types | |||
| 473 | data_ &= fractional_mask; | 452 | data_ &= fractional_mask; |
| 474 | } | 453 | } |
| 475 | 454 | ||
| 476 | constexpr base_type get_frac() const { | 455 | [[nodiscard]] constexpr base_type get_frac() const { |
| 477 | return data_ & fractional_mask; | 456 | return data_ & fractional_mask; |
| 478 | } | 457 | } |
| 479 | 458 | ||
| 480 | public: | 459 | public: |
| 481 | constexpr void swap(FixedPoint& rhs) { | 460 | constexpr void swap(FixedPoint& rhs) noexcept { |
| 482 | using std::swap; | 461 | using std::swap; |
| 483 | swap(data_, rhs.data_); | 462 | swap(data_, rhs.data_); |
| 484 | } | 463 | } |
| 485 | 464 | ||
| 486 | public: | 465 | public: |
| 487 | base_type data_; | 466 | base_type data_{}; |
| 488 | }; | 467 | }; |
| 489 | 468 | ||
| 490 | // if we have the same fractional portion, but differing integer portions, we trivially upgrade the | 469 | // if we have the same fractional portion, but differing integer portions, we trivially upgrade the |
| 491 | // smaller type | 470 | // smaller type |
| 492 | template <size_t I1, size_t I2, size_t F> | 471 | template <size_t I1, size_t I2, size_t F> |
| 493 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator+( | 472 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator+( |
| 494 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 473 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 495 | 474 | ||
| 496 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 475 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 497 | 476 | ||
| 498 | const T l = T::from_base(lhs.to_raw()); | 477 | const T l = T::from_base(lhs.to_raw()); |
| 499 | const T r = T::from_base(rhs.to_raw()); | 478 | const T r = T::from_base(rhs.to_raw()); |
| @@ -501,10 +480,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 501 | } | 480 | } |
| 502 | 481 | ||
| 503 | template <size_t I1, size_t I2, size_t F> | 482 | template <size_t I1, size_t I2, size_t F> |
| 504 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator-( | 483 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator-( |
| 505 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 484 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 506 | 485 | ||
| 507 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 486 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 508 | 487 | ||
| 509 | const T l = T::from_base(lhs.to_raw()); | 488 | const T l = T::from_base(lhs.to_raw()); |
| 510 | const T r = T::from_base(rhs.to_raw()); | 489 | const T r = T::from_base(rhs.to_raw()); |
| @@ -512,10 +491,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 512 | } | 491 | } |
| 513 | 492 | ||
| 514 | template <size_t I1, size_t I2, size_t F> | 493 | template <size_t I1, size_t I2, size_t F> |
| 515 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator*( | 494 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator*( |
| 516 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 495 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 517 | 496 | ||
| 518 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 497 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 519 | 498 | ||
| 520 | const T l = T::from_base(lhs.to_raw()); | 499 | const T l = T::from_base(lhs.to_raw()); |
| 521 | const T r = T::from_base(rhs.to_raw()); | 500 | const T r = T::from_base(rhs.to_raw()); |
| @@ -523,10 +502,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 523 | } | 502 | } |
| 524 | 503 | ||
| 525 | template <size_t I1, size_t I2, size_t F> | 504 | template <size_t I1, size_t I2, size_t F> |
| 526 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator/( | 505 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator/( |
| 527 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 506 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 528 | 507 | ||
| 529 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 508 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 530 | 509 | ||
| 531 | const T l = T::from_base(lhs.to_raw()); | 510 | const T l = T::from_base(lhs.to_raw()); |
| 532 | const T r = T::from_base(rhs.to_raw()); | 511 | const T r = T::from_base(rhs.to_raw()); |
| @@ -561,54 +540,46 @@ constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) | |||
| 561 | return lhs; | 540 | return lhs; |
| 562 | } | 541 | } |
| 563 | 542 | ||
| 564 | template <size_t I, size_t F, class Number, | 543 | template <size_t I, size_t F, IsArithmetic Number> |
| 565 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 566 | constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { | 544 | constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { |
| 567 | lhs += FixedPoint<I, F>(rhs); | 545 | lhs += FixedPoint<I, F>(rhs); |
| 568 | return lhs; | 546 | return lhs; |
| 569 | } | 547 | } |
| 570 | template <size_t I, size_t F, class Number, | 548 | template <size_t I, size_t F, IsArithmetic Number> |
| 571 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 572 | constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { | 549 | constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { |
| 573 | lhs -= FixedPoint<I, F>(rhs); | 550 | lhs -= FixedPoint<I, F>(rhs); |
| 574 | return lhs; | 551 | return lhs; |
| 575 | } | 552 | } |
| 576 | template <size_t I, size_t F, class Number, | 553 | template <size_t I, size_t F, IsArithmetic Number> |
| 577 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 578 | constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { | 554 | constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { |
| 579 | lhs *= FixedPoint<I, F>(rhs); | 555 | lhs *= FixedPoint<I, F>(rhs); |
| 580 | return lhs; | 556 | return lhs; |
| 581 | } | 557 | } |
| 582 | template <size_t I, size_t F, class Number, | 558 | template <size_t I, size_t F, IsArithmetic Number> |
| 583 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 584 | constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { | 559 | constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { |
| 585 | lhs /= FixedPoint<I, F>(rhs); | 560 | lhs /= FixedPoint<I, F>(rhs); |
| 586 | return lhs; | 561 | return lhs; |
| 587 | } | 562 | } |
| 588 | 563 | ||
| 589 | template <size_t I, size_t F, class Number, | 564 | template <size_t I, size_t F, IsArithmetic Number> |
| 590 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 591 | constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { | 565 | constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { |
| 592 | FixedPoint<I, F> tmp(lhs); | 566 | FixedPoint<I, F> tmp(lhs); |
| 593 | tmp += rhs; | 567 | tmp += rhs; |
| 594 | return tmp; | 568 | return tmp; |
| 595 | } | 569 | } |
| 596 | template <size_t I, size_t F, class Number, | 570 | template <size_t I, size_t F, IsArithmetic Number> |
| 597 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 598 | constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { | 571 | constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { |
| 599 | FixedPoint<I, F> tmp(lhs); | 572 | FixedPoint<I, F> tmp(lhs); |
| 600 | tmp -= rhs; | 573 | tmp -= rhs; |
| 601 | return tmp; | 574 | return tmp; |
| 602 | } | 575 | } |
| 603 | template <size_t I, size_t F, class Number, | 576 | template <size_t I, size_t F, IsArithmetic Number> |
| 604 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 605 | constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { | 577 | constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { |
| 606 | FixedPoint<I, F> tmp(lhs); | 578 | FixedPoint<I, F> tmp(lhs); |
| 607 | tmp *= rhs; | 579 | tmp *= rhs; |
| 608 | return tmp; | 580 | return tmp; |
| 609 | } | 581 | } |
| 610 | template <size_t I, size_t F, class Number, | 582 | template <size_t I, size_t F, IsArithmetic Number> |
| 611 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 612 | constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { | 583 | constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { |
| 613 | FixedPoint<I, F> tmp(lhs); | 584 | FixedPoint<I, F> tmp(lhs); |
| 614 | tmp /= rhs; | 585 | tmp /= rhs; |
| @@ -616,78 +587,64 @@ constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { | |||
| 616 | } | 587 | } |
| 617 | 588 | ||
| 618 | // shift operators | 589 | // shift operators |
| 619 | template <size_t I, size_t F, class Integer, | 590 | template <size_t I, size_t F, IsIntegral Integer> |
| 620 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 621 | constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { | 591 | constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { |
| 622 | lhs <<= rhs; | 592 | lhs <<= rhs; |
| 623 | return lhs; | 593 | return lhs; |
| 624 | } | 594 | } |
| 625 | template <size_t I, size_t F, class Integer, | 595 | template <size_t I, size_t F, IsIntegral Integer> |
| 626 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 627 | constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { | 596 | constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { |
| 628 | lhs >>= rhs; | 597 | lhs >>= rhs; |
| 629 | return lhs; | 598 | return lhs; |
| 630 | } | 599 | } |
| 631 | 600 | ||
| 632 | // comparison operators | 601 | // comparison operators |
| 633 | template <size_t I, size_t F, class Number, | 602 | template <size_t I, size_t F, IsArithmetic Number> |
| 634 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 635 | constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) { | 603 | constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) { |
| 636 | return lhs > FixedPoint<I, F>(rhs); | 604 | return lhs > FixedPoint<I, F>(rhs); |
| 637 | } | 605 | } |
| 638 | template <size_t I, size_t F, class Number, | 606 | template <size_t I, size_t F, IsArithmetic Number> |
| 639 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 640 | constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) { | 607 | constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) { |
| 641 | return lhs < FixedPoint<I, F>(rhs); | 608 | return lhs < FixedPoint<I, F>(rhs); |
| 642 | } | 609 | } |
| 643 | template <size_t I, size_t F, class Number, | 610 | template <size_t I, size_t F, IsArithmetic Number> |
| 644 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 645 | constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) { | 611 | constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) { |
| 646 | return lhs >= FixedPoint<I, F>(rhs); | 612 | return lhs >= FixedPoint<I, F>(rhs); |
| 647 | } | 613 | } |
| 648 | template <size_t I, size_t F, class Number, | 614 | template <size_t I, size_t F, IsArithmetic Number> |
| 649 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 650 | constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) { | 615 | constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) { |
| 651 | return lhs <= FixedPoint<I, F>(rhs); | 616 | return lhs <= FixedPoint<I, F>(rhs); |
| 652 | } | 617 | } |
| 653 | template <size_t I, size_t F, class Number, | 618 | template <size_t I, size_t F, IsArithmetic Number> |
| 654 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 655 | constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) { | 619 | constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) { |
| 656 | return lhs == FixedPoint<I, F>(rhs); | 620 | return lhs == FixedPoint<I, F>(rhs); |
| 657 | } | 621 | } |
| 658 | template <size_t I, size_t F, class Number, | 622 | template <size_t I, size_t F, IsArithmetic Number> |
| 659 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 660 | constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) { | 623 | constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) { |
| 661 | return lhs != FixedPoint<I, F>(rhs); | 624 | return lhs != FixedPoint<I, F>(rhs); |
| 662 | } | 625 | } |
| 663 | 626 | ||
| 664 | template <size_t I, size_t F, class Number, | 627 | template <size_t I, size_t F, IsArithmetic Number> |
| 665 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 666 | constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) { | 628 | constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) { |
| 667 | return FixedPoint<I, F>(lhs) > rhs; | 629 | return FixedPoint<I, F>(lhs) > rhs; |
| 668 | } | 630 | } |
| 669 | template <size_t I, size_t F, class Number, | 631 | template <size_t I, size_t F, IsArithmetic Number> |
| 670 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 671 | constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) { | 632 | constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) { |
| 672 | return FixedPoint<I, F>(lhs) < rhs; | 633 | return FixedPoint<I, F>(lhs) < rhs; |
| 673 | } | 634 | } |
| 674 | template <size_t I, size_t F, class Number, | 635 | template <size_t I, size_t F, IsArithmetic Number> |
| 675 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 676 | constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) { | 636 | constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) { |
| 677 | return FixedPoint<I, F>(lhs) >= rhs; | 637 | return FixedPoint<I, F>(lhs) >= rhs; |
| 678 | } | 638 | } |
| 679 | template <size_t I, size_t F, class Number, | 639 | template <size_t I, size_t F, IsArithmetic Number> |
| 680 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 681 | constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) { | 640 | constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) { |
| 682 | return FixedPoint<I, F>(lhs) <= rhs; | 641 | return FixedPoint<I, F>(lhs) <= rhs; |
| 683 | } | 642 | } |
| 684 | template <size_t I, size_t F, class Number, | 643 | template <size_t I, size_t F, IsArithmetic Number> |
| 685 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 686 | constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) { | 644 | constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) { |
| 687 | return FixedPoint<I, F>(lhs) == rhs; | 645 | return FixedPoint<I, F>(lhs) == rhs; |
| 688 | } | 646 | } |
| 689 | template <size_t I, size_t F, class Number, | 647 | template <size_t I, size_t F, IsArithmetic Number> |
| 690 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 691 | constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) { | 648 | constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) { |
| 692 | return FixedPoint<I, F>(lhs) != rhs; | 649 | return FixedPoint<I, F>(lhs) != rhs; |
| 693 | } | 650 | } |