openMSX
FixedPoint.hh
Go to the documentation of this file.
1 #ifndef FIXEDPOINT_HH
2 #define FIXEDPOINT_HH
3 
4 #include "serialize.hh"
5 #include <cmath>
6 #include <cstdint>
7 
8 namespace openmsx {
9 
14 template<unsigned FRACTION_BITS_>
15 class FixedPoint {
16 public:
19  static constexpr unsigned FRACTION_BITS = FRACTION_BITS_;
20 
21 private:
24  static constexpr int ONE = 1 << FRACTION_BITS;
25 
28  static constexpr float INV_ONE_F = 1.0f / ONE;
29 
32  static constexpr double INV_ONE_D = 1.0 / ONE;
33 
37  static constexpr int FRACTION_MASK = ONE - 1;
38 
39 public:
44  [[nodiscard]] static constexpr FixedPoint create(int value) {
45  return FixedPoint(value, CreateRawTag{});
46  }
47 
50  constexpr FixedPoint() = default;
51 
52  // Conversion to fixed point:
53 
54  explicit constexpr FixedPoint(int i) : value(i << FRACTION_BITS) {}
55  explicit constexpr FixedPoint(unsigned i) : value(i << FRACTION_BITS) {}
56  explicit FixedPoint(float f) : value(lrintf(f * ONE)) {}
57  explicit FixedPoint(double d) : value(lrint (d * ONE)) {}
58 
59  [[nodiscard]] static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d) {
60  return create((static_cast<uint64_t>(n) << FRACTION_BITS) / d);
61  }
62 
63  [[nodiscard]] static constexpr int shiftHelper(int x, int s) {
64  return (s >= 0) ? (x >> s) : (x << -s);
65  }
66  template<unsigned BITS2>
67  explicit constexpr FixedPoint(FixedPoint<BITS2> other)
68  : value(shiftHelper(other.getRawValue(), BITS2 - FRACTION_BITS)) {}
69 
70  // Conversion from fixed point:
71 
76  [[nodiscard]] constexpr int toInt() const {
77  return value >> FRACTION_BITS;
78  }
79 
83  [[nodiscard]] constexpr float toFloat() const {
84  return value * INV_ONE_F;
85  }
86 
90  [[nodiscard]] constexpr double toDouble() const {
91  return value * INV_ONE_D;
92  }
93 
100  [[nodiscard]] constexpr float fractionAsFloat() const {
101  return (value & FRACTION_MASK) * INV_ONE_F;
102  }
103 
110  [[nodiscard]] constexpr double fractionAsDouble() const {
111  return (value & FRACTION_MASK) * INV_ONE_D;
112  }
113 
114  // Various arithmetic:
115 
120  [[nodiscard]] constexpr int divAsInt(FixedPoint other) const {
121  return value / other.value;
122  }
123 
128  [[nodiscard]] constexpr FixedPoint floor() const {
129  return create(value & ~FRACTION_MASK);
130  }
131 
136  [[nodiscard]] constexpr FixedPoint fract() const {
137  return create(value & FRACTION_MASK);
138  }
139 
144  [[nodiscard]] constexpr unsigned fractAsInt() const {
145  return value & FRACTION_MASK;
146  }
147 
148  // Arithmetic operators:
149 
150  [[nodiscard]] constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y) {
151  return create(x.value + y.value);
152  }
153  [[nodiscard]] constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y) {
154  return create(x.value - y.value);
155  }
156  [[nodiscard]] constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y) {
157  return create(int(
158  (static_cast<int64_t>(x.value) * y.value) >> FRACTION_BITS));
159  }
160  [[nodiscard]] constexpr friend FixedPoint operator*(FixedPoint x, int y) {
161  return create(x.value * y);
162  }
163  [[nodiscard]] constexpr friend FixedPoint operator*(int x, FixedPoint y) {
164  return create(x * y.value);
165  }
170  [[nodiscard]] constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y) {
171  return create(int(
172  (static_cast<int64_t>(x.value) << FRACTION_BITS) / y.value));
173  }
174  [[nodiscard]] constexpr friend FixedPoint operator/(FixedPoint x, int y) {
175  return create(x.value / y);
176  }
177  [[nodiscard]] constexpr friend FixedPoint operator<<(FixedPoint x, int y) {
178  return create(x.value << y);
179  }
180  [[nodiscard]] constexpr friend FixedPoint operator>>(FixedPoint x, int y) {
181  return create(x.value >> y);
182  }
183 
184  // Comparison operators:
185 
186  [[nodiscard]] constexpr friend bool operator==(FixedPoint x, FixedPoint y) {
187  return x.value == y.value;
188  }
189  [[nodiscard]] constexpr friend bool operator!=(FixedPoint x, FixedPoint y) {
190  return x.value != y.value;
191  }
192  [[nodiscard]] constexpr friend bool operator<(FixedPoint x, FixedPoint y) {
193  return x.value < y.value;
194  }
195  [[nodiscard]] constexpr friend bool operator<=(FixedPoint x, FixedPoint y) {
196  return x.value <= y.value;
197  }
198  [[nodiscard]] constexpr friend bool operator>(FixedPoint x, FixedPoint y) {
199  return x.value > y.value;
200  }
201  [[nodiscard]] constexpr friend bool operator>=(FixedPoint x, FixedPoint y) {
202  return x.value >= y.value;
203  }
204 
205  // Arithmetic operators that modify this object:
206 
207  void operator+=(FixedPoint other) {
208  value += other.value;
209  }
210  void operator-=(FixedPoint other) {
211  value -= other.value;
212  }
213 
217  void addQuantum() {
218  value += 1;
219  }
220 
221  // Should only be used by other instances of this class
222  // templatized friend declarations are not possible in c++
223  [[nodiscard]] constexpr int getRawValue() const {
224  return value;
225  }
226 
227  template<typename Archive>
228  void serialize(Archive& ar, unsigned /*version*/)
229  {
230  ar.serialize("value", value);
231  }
232 
233 private:
234  struct CreateRawTag {};
235  constexpr FixedPoint(int raw_value, CreateRawTag)
236  : value(raw_value) {}
237 
238  int value = 0;
239 };
240 
241 } // namespace openmsx
242 
243 #endif // FIXEDPOINT_HH
constexpr int getRawValue() const
Definition: FixedPoint.hh:223
constexpr friend FixedPoint operator*(FixedPoint x, int y)
Definition: FixedPoint.hh:160
static constexpr int shiftHelper(int x, int s)
Definition: FixedPoint.hh:63
constexpr friend bool operator==(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:186
constexpr friend bool operator<=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:195
void operator+=(FixedPoint other)
Definition: FixedPoint.hh:207
constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:153
constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:150
static constexpr unsigned FRACTION_BITS
Number of fractional bits (export template parameter as a constant so that external code can use it m...
Definition: FixedPoint.hh:19
void serialize(Archive &ar, unsigned)
Definition: FixedPoint.hh:228
constexpr friend bool operator!=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:189
constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y)
Divides two fixed point numbers.
Definition: FixedPoint.hh:170
constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:156
constexpr friend FixedPoint operator*(int x, FixedPoint y)
Definition: FixedPoint.hh:163
static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d)
Definition: FixedPoint.hh:59
constexpr double toDouble() const
Returns the double value that corresponds to this fixed point number.
Definition: FixedPoint.hh:90
A fixed point number, implemented by a 32-bit signed integer.
Definition: FixedPoint.hh:15
void operator-=(FixedPoint other)
Definition: FixedPoint.hh:210
constexpr friend FixedPoint operator/(FixedPoint x, int y)
Definition: FixedPoint.hh:174
constexpr FixedPoint fract() const
Returns the fractional part of this value.
Definition: FixedPoint.hh:136
constexpr FixedPoint(FixedPoint< BITS2 > other)
Definition: FixedPoint.hh:67
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
constexpr FixedPoint()=default
Creates a zero-initialized fixed point object.
constexpr FixedPoint(unsigned i)
Definition: FixedPoint.hh:55
constexpr friend bool operator>=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:201
FixedPoint(double d)
Definition: FixedPoint.hh:57
void addQuantum()
Increase this value with the smallest possible amount.
Definition: FixedPoint.hh:217
constexpr unsigned fractAsInt() const
Returns the fractional part of this value as an integer.
Definition: FixedPoint.hh:144
constexpr friend FixedPoint operator>>(FixedPoint x, int y)
Definition: FixedPoint.hh:180
constexpr int divAsInt(FixedPoint other) const
Returns the result of a division between this fixed point number and another, rounded towards zero...
Definition: FixedPoint.hh:120
constexpr FixedPoint floor() const
Returns this value rounded down.
Definition: FixedPoint.hh:128
constexpr friend FixedPoint operator<<(FixedPoint x, int y)
Definition: FixedPoint.hh:177
constexpr float toFloat() const
Returns the float value that corresponds to this fixed point number.
Definition: FixedPoint.hh:83
constexpr float fractionAsFloat() const
Returns the fractional part of this fixed point number as a float.
Definition: FixedPoint.hh:100
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1377
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition: FixedPoint.hh:76
constexpr friend bool operator<(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:192
static constexpr FixedPoint create(int value)
Create new fixed point object from given representation.
Definition: FixedPoint.hh:44
constexpr double fractionAsDouble() const
Returns the fractional part of this fixed point number as a double.
Definition: FixedPoint.hh:110
constexpr FixedPoint(int i)
Definition: FixedPoint.hh:54
constexpr friend bool operator>(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:198