openMSX
FixedPoint.hh
Go to the documentation of this file.
1#ifndef FIXEDPOINT_HH
2#define FIXEDPOINT_HH
3
4#include "narrow.hh"
5#include "serialize.hh"
6#include <cmath>
7#include <cstdint>
8
9namespace openmsx {
10
15template<unsigned FRACTION_BITS_>
17public:
20 static constexpr unsigned FRACTION_BITS = FRACTION_BITS_;
21
22private:
25 static constexpr int ONE = 1 << FRACTION_BITS;
26
29 static constexpr float INV_ONE_F = 1.0f / ONE;
30
33 static constexpr double INV_ONE_D = 1.0 / ONE;
34
38 static constexpr int FRACTION_MASK = ONE - 1;
39
40public:
45 [[nodiscard]] static constexpr FixedPoint create(int value) {
46 return FixedPoint(value, CreateRawTag{});
47 }
48
51 constexpr FixedPoint() = default;
52
53 // Conversion to fixed point:
54
55 explicit constexpr FixedPoint(int i) : value(i << FRACTION_BITS) {}
56 explicit constexpr FixedPoint(unsigned i) : value(i << FRACTION_BITS) {}
57 explicit FixedPoint(float f) : value(narrow_cast<int>(lrintf(f * ONE))) {}
58 explicit FixedPoint(double d) : value(narrow_cast<int>(lrint (d * ONE))) {}
59
60 [[nodiscard]] static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d) {
61 return create(narrow_cast<int>((static_cast<uint64_t>(n) << FRACTION_BITS) / d));
62 }
63
64 [[nodiscard]] static constexpr int shiftHelper(int x, int s) {
65 return (s >= 0) ? (x >> s) : (x << -s);
66 }
67 template<unsigned BITS2>
68 explicit constexpr FixedPoint(FixedPoint<BITS2> other)
69 : value(shiftHelper(other.getRawValue(), BITS2 - FRACTION_BITS)) {}
70
71 // Conversion from fixed point:
72
77 [[nodiscard]] constexpr int toInt() const {
78 return value >> FRACTION_BITS;
79 }
80
84 [[nodiscard]] constexpr float toFloat() const {
85 return narrow_cast<float>(value) * INV_ONE_F;
86 }
87
91 [[nodiscard]] constexpr double toDouble() const {
92 return narrow_cast<double>(value) * INV_ONE_D;
93 }
94
101 [[nodiscard]] constexpr float fractionAsFloat() const {
102 return narrow_cast<float>(value & FRACTION_MASK) * INV_ONE_F;
103 }
104
111 [[nodiscard]] constexpr double fractionAsDouble() const {
112 return narrow_cast<double>(value & FRACTION_MASK) * INV_ONE_D;
113 }
114
115 // Various arithmetic:
116
121 [[nodiscard]] constexpr int divAsInt(FixedPoint other) const {
122 return value / other.value;
123 }
124
129 [[nodiscard]] constexpr FixedPoint floor() const {
130 return create(value & ~FRACTION_MASK);
131 }
132
137 [[nodiscard]] constexpr FixedPoint fract() const {
138 return create(value & FRACTION_MASK);
139 }
140
145 [[nodiscard]] constexpr unsigned fractAsInt() const {
146 return value & FRACTION_MASK;
147 }
148
149 // Arithmetic operators:
150
151 [[nodiscard]] constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y) {
152 return create(x.value + y.value);
153 }
154 [[nodiscard]] constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y) {
155 return create(x.value - y.value);
156 }
157 [[nodiscard]] constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y) {
158 return create(int(
159 (static_cast<int64_t>(x.value) * y.value) >> FRACTION_BITS));
160 }
161 [[nodiscard]] constexpr friend FixedPoint operator*(FixedPoint x, int y) {
162 return create(x.value * y);
163 }
164 [[nodiscard]] constexpr friend FixedPoint operator*(int x, FixedPoint y) {
165 return create(x * y.value);
166 }
171 [[nodiscard]] constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y) {
172 return create(int(
173 (static_cast<int64_t>(x.value) << FRACTION_BITS) / y.value));
174 }
175 [[nodiscard]] constexpr friend FixedPoint operator/(FixedPoint x, int y) {
176 return create(x.value / y);
177 }
178 [[nodiscard]] constexpr friend FixedPoint operator<<(FixedPoint x, int y) {
179 return create(x.value << y);
180 }
181 [[nodiscard]] constexpr friend FixedPoint operator>>(FixedPoint x, int y) {
182 return create(x.value >> y);
183 }
184
185 // Comparison operators:
186 [[nodiscard]] constexpr auto operator<=>(const FixedPoint&) const = default;
187
188 // Arithmetic operators that modify this object:
189
190 constexpr void operator+=(FixedPoint other) {
191 value += other.value;
192 }
193 constexpr void operator-=(FixedPoint other) {
194 value -= other.value;
195 }
196
200 constexpr void addQuantum() {
201 value += 1;
202 }
203
204 // Should only be used by other instances of this class
205 // templatized friend declarations are not possible in c++
206 [[nodiscard]] constexpr int getRawValue() const {
207 return value;
208 }
209
210 template<typename Archive>
211 void serialize(Archive& ar, unsigned /*version*/)
212 {
213 ar.serialize("value", value);
214 }
215
216private:
217 struct CreateRawTag {};
218 constexpr FixedPoint(int raw_value, CreateRawTag)
219 : value(raw_value) {}
220
221 int value = 0;
222};
223
224} // namespace openmsx
225
226#endif // FIXEDPOINT_HH
A fixed point number, implemented by a 32-bit signed integer.
Definition FixedPoint.hh:16
static constexpr FixedPoint create(int value)
Create new fixed point object from given representation.
Definition FixedPoint.hh:45
constexpr friend FixedPoint operator-(FixedPoint x, FixedPoint y)
constexpr void operator-=(FixedPoint other)
static constexpr FixedPoint roundRatioDown(unsigned n, unsigned d)
Definition FixedPoint.hh:60
constexpr int divAsInt(FixedPoint other) const
Returns the result of a division between this fixed point number and another, rounded towards zero.
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:20
constexpr friend FixedPoint operator*(FixedPoint x, int y)
constexpr double fractionAsDouble() const
Returns the fractional part of this fixed point number as a double.
constexpr FixedPoint(unsigned i)
Definition FixedPoint.hh:56
constexpr double toDouble() const
Returns the double value that corresponds to this fixed point number.
Definition FixedPoint.hh:91
constexpr friend FixedPoint operator/(FixedPoint x, FixedPoint y)
Divides two fixed point numbers.
constexpr friend FixedPoint operator*(FixedPoint x, FixedPoint y)
constexpr friend FixedPoint operator>>(FixedPoint x, int y)
constexpr FixedPoint fract() const
Returns the fractional part of this value.
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition FixedPoint.hh:77
constexpr friend FixedPoint operator*(int x, FixedPoint y)
constexpr FixedPoint(int i)
Definition FixedPoint.hh:55
constexpr int getRawValue() const
constexpr float toFloat() const
Returns the float value that corresponds to this fixed point number.
Definition FixedPoint.hh:84
static constexpr int shiftHelper(int x, int s)
Definition FixedPoint.hh:64
constexpr unsigned fractAsInt() const
Returns the fractional part of this value as an integer.
constexpr float fractionAsFloat() const
Returns the fractional part of this fixed point number as a float.
constexpr friend FixedPoint operator<<(FixedPoint x, int y)
constexpr FixedPoint(FixedPoint< BITS2 > other)
Definition FixedPoint.hh:68
constexpr friend FixedPoint operator+(FixedPoint x, FixedPoint y)
constexpr void addQuantum()
Increase this value with the smallest possible amount.
constexpr friend FixedPoint operator/(FixedPoint x, int y)
void serialize(Archive &ar, unsigned)
constexpr FixedPoint()=default
Creates a zero-initialized fixed point object.
constexpr auto operator<=>(const FixedPoint &) const =default
constexpr void operator+=(FixedPoint other)
constexpr FixedPoint floor() const
Returns this value rounded down.
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr To narrow_cast(From &&from) noexcept
Definition narrow.hh:21