openMSX
FixedPoint.hh
Go to the documentation of this file.
1 #ifndef FIXEDPOINT_HH
2 #define FIXEDPOINT_HH
3 
4 #include <cmath>
5 #include <cstdint>
6 
7 namespace openmsx {
8 
13 template<unsigned FRACTION_BITS_>
14 class FixedPoint {
15 public:
18  static constexpr unsigned FRACTION_BITS = FRACTION_BITS_;
19 
20 private:
23  static constexpr int ONE = 1 << FRACTION_BITS;
24 
27  static constexpr float INV_ONE_F = 1.0f / ONE;
28 
31  static constexpr double INV_ONE_D = 1.0 / ONE;
32 
36  static constexpr int FRACTION_MASK = ONE - 1;
37 
38 public:
43  static constexpr FixedPoint create(int value) {
44  return FixedPoint(value, CreateRawTag{});
45  }
46 
49  explicit constexpr FixedPoint() = default;
50 
51  // Conversion to fixed point:
52 
53  explicit constexpr FixedPoint(int i) : value(i << FRACTION_BITS) {}
54  explicit constexpr FixedPoint(unsigned i) : value(i << FRACTION_BITS) {}
55  explicit FixedPoint(float f) : value(lrintf(f * ONE)) {}
56  explicit FixedPoint(double d) : value(lrint (d * ONE)) {}
57 
58  static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d) {
59  return create((static_cast<uint64_t>(n) << FRACTION_BITS) / d);
60  }
61 
62  static constexpr int shiftHelper(int x, int s) {
63  return (s >= 0) ? (x >> s) : (x << -s);
64  }
65  template<unsigned BITS2>
66  explicit constexpr FixedPoint(FixedPoint<BITS2> other)
67  : value(shiftHelper(other.getRawValue(), BITS2 - FRACTION_BITS)) {}
68 
69  // Conversion from fixed point:
70 
75  constexpr int toInt() const {
76  return value >> FRACTION_BITS;
77  }
78 
82  constexpr float toFloat() const {
83  return value * INV_ONE_F;
84  }
85 
89  constexpr double toDouble() const {
90  return value * INV_ONE_D;
91  }
92 
99  constexpr float fractionAsFloat() const {
100  return (value & FRACTION_MASK) * INV_ONE_F;
101  }
102 
109  constexpr double fractionAsDouble() const {
110  return (value & FRACTION_MASK) * INV_ONE_D;
111  }
112 
113  // Various arithmetic:
114 
119  constexpr int divAsInt(FixedPoint other) const {
120  return value / other.value;
121  }
122 
127  constexpr FixedPoint floor() const {
128  return create(value & ~FRACTION_MASK);
129  }
130 
135  constexpr FixedPoint fract() const {
136  return create(value & FRACTION_MASK);
137  }
138 
143  constexpr unsigned fractAsInt() const {
144  return value & FRACTION_MASK;
145  }
146 
147  // Arithmetic operators:
148 
149  constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y) {
150  return create(x.value + y.value);
151  }
152  constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y) {
153  return create(x.value - y.value);
154  }
155  constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y) {
156  return create(int(
157  (static_cast<int64_t>(x.value) * y.value) >> FRACTION_BITS));
158  }
159  constexpr friend FixedPoint operator*(FixedPoint x, int y) {
160  return create(x.value * y);
161  }
162  constexpr friend FixedPoint operator*(int x, FixedPoint y) {
163  return create(x * y.value);
164  }
169  constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y) {
170  return create(int(
171  (static_cast<int64_t>(x.value) << FRACTION_BITS) / y.value));
172  }
173  constexpr friend FixedPoint operator/(FixedPoint x, int y) {
174  return create(x.value / y);
175  }
176  constexpr friend FixedPoint operator<<(FixedPoint x, int y) {
177  return create(x.value << y);
178  }
179  constexpr friend FixedPoint operator>>(FixedPoint x, int y) {
180  return create(x.value >> y);
181  }
182 
183  // Comparison operators:
184 
185  constexpr friend bool operator==(FixedPoint x, FixedPoint y) {
186  return x.value == y.value;
187  }
188  constexpr friend bool operator!=(FixedPoint x, FixedPoint y) {
189  return x.value != y.value;
190  }
191  constexpr friend bool operator<(FixedPoint x, FixedPoint y) {
192  return x.value < y.value;
193  }
194  constexpr friend bool operator<=(FixedPoint x, FixedPoint y) {
195  return x.value <= y.value;
196  }
197  constexpr friend bool operator>(FixedPoint x, FixedPoint y) {
198  return x.value > y.value;
199  }
200  constexpr friend bool operator>=(FixedPoint x, FixedPoint y) {
201  return x.value >= y.value;
202  }
203 
204  // Arithmetic operators that modify this object:
205 
206  void operator+=(FixedPoint other) {
207  value += other.value;
208  }
209  void operator-=(FixedPoint other) {
210  value -= other.value;
211  }
212 
216  void addQuantum() {
217  value += 1;
218  }
219 
220  // Should only be used by other instances of this class
221  // templatized friend declarations are not possible in c++
222  constexpr int getRawValue() const {
223  return value;
224  }
225 
226  template<typename Archive>
227  void serialize(Archive& ar, unsigned /*version*/)
228  {
229  ar.serialize("value", value);
230  }
231 
232 private:
233  struct CreateRawTag {};
234  constexpr FixedPoint(int raw_value, CreateRawTag)
235  : value(raw_value) {}
236 
237  int value = 0;
238 };
239 
240 } // namespace openmsx
241 
242 #endif // FIXEDPOINT_HH
constexpr int getRawValue() const
Definition: FixedPoint.hh:222
constexpr friend FixedPoint operator*(FixedPoint x, int y)
Definition: FixedPoint.hh:159
static constexpr int shiftHelper(int x, int s)
Definition: FixedPoint.hh:62
constexpr friend bool operator==(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:185
constexpr friend bool operator<=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:194
void operator+=(FixedPoint other)
Definition: FixedPoint.hh:206
constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:152
constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:149
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:18
void serialize(Archive &ar, unsigned)
Definition: FixedPoint.hh:227
constexpr friend bool operator!=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:188
constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y)
Divides two fixed point numbers.
Definition: FixedPoint.hh:169
constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:155
constexpr friend FixedPoint operator*(int x, FixedPoint y)
Definition: FixedPoint.hh:162
static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d)
Definition: FixedPoint.hh:58
constexpr double toDouble() const
Returns the double value that corresponds to this fixed point number.
Definition: FixedPoint.hh:89
A fixed point number, implemented by a 32-bit signed integer.
Definition: FixedPoint.hh:14
void operator-=(FixedPoint other)
Definition: FixedPoint.hh:209
constexpr friend FixedPoint operator/(FixedPoint x, int y)
Definition: FixedPoint.hh:173
constexpr FixedPoint fract() const
Returns the fractional part of this value.
Definition: FixedPoint.hh:135
constexpr FixedPoint(FixedPoint< BITS2 > other)
Definition: FixedPoint.hh:66
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:54
constexpr friend bool operator>=(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:200
FixedPoint(double d)
Definition: FixedPoint.hh:56
void addQuantum()
Increase this value with the smallest possible amount.
Definition: FixedPoint.hh:216
constexpr unsigned fractAsInt() const
Returns the fractional part of this value as an integer.
Definition: FixedPoint.hh:143
constexpr friend FixedPoint operator>>(FixedPoint x, int y)
Definition: FixedPoint.hh:179
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:119
constexpr FixedPoint floor() const
Returns this value rounded down.
Definition: FixedPoint.hh:127
constexpr friend FixedPoint operator<<(FixedPoint x, int y)
Definition: FixedPoint.hh:176
constexpr float toFloat() const
Returns the float value that corresponds to this fixed point number.
Definition: FixedPoint.hh:82
constexpr float fractionAsFloat() const
Returns the fractional part of this fixed point number as a float.
Definition: FixedPoint.hh:99
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition: FixedPoint.hh:75
constexpr friend bool operator<(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:191
static constexpr FixedPoint create(int value)
Create new fixed point object from given representation.
Definition: FixedPoint.hh:43
constexpr double fractionAsDouble() const
Returns the fractional part of this fixed point number as a double.
Definition: FixedPoint.hh:109
constexpr FixedPoint(int i)
Definition: FixedPoint.hh:53
constexpr friend bool operator>(FixedPoint x, FixedPoint y)
Definition: FixedPoint.hh:197