14 /// Fixed point number type.
15 /// The first bit is used for the sign (0 = positive, 1 = negative), the last
16 /// fracBits bits are used for the fractional part and the remaining middle
17 /// bits represent the integer value.
18 /// The sign bit of zero is undefined.
19 template<Uint8 fracBits>
26 /// Create a fixed point decimal representing i/f .
27 Fixed(Sint32 i = 0, Uint32 f = 1)
28 : rep(((i < 0 ? (i * -1) : i) << IntShift()) & IntMask()) {
34 explicit Fixed(double d)
36 rep = std::abs(d) * (1 << IntShift());
41 template<Uint8 otherFrac>
42 explicit Fixed(const Fixed<otherFrac> &other)
44 Uint32 otherInt = other.RawInt();
45 rep = DistanceShift(otherInt, fracBits, otherFrac);
46 if (other.Sigma() < 0) {
52 int Int() const { return IntPart() * Sigma(); }
56 } else if (SignPart() == 0) {
62 double Double() const { return double(SignedInt()) / (1 << IntShift()); }
65 bool operator ==(const Fixed &other) const {
66 return rep == other.rep;
68 bool operator !=(const Fixed &other) const {
69 return rep != other.rep;
71 bool operator <(const Fixed &other) const {
72 return SignedInt() < other.SignedInt();
74 bool operator <=(const Fixed &other) const {
75 return SignedInt() <= other.SignedInt();
77 bool operator >(const Fixed &other) const {
78 return SignedInt() > other.SignedInt();
80 bool operator >=(const Fixed &other) const {
81 return SignedInt() >= other.SignedInt();
84 Fixed operator -() const {
86 neg.rep = rep ^ SignMask();
90 Fixed &operator +=(const Fixed &other) {
91 Sint32 temp = SignedInt() + other.SignedInt();
93 rep = (temp * -1) | SignMask();
99 template<class Scalar>
100 Fixed &operator +=(Scalar i) {
101 Sint32 temp = SignedInt() + (i << IntShift());
103 rep = (temp * -1) | SignMask();
109 Fixed &operator -=(const Fixed &other) {
110 Sint32 temp = SignedInt() - other.SignedInt();
112 rep = (temp * -1) | SignMask();
118 template<class Scalar>
119 Fixed &operator -=(Scalar i) {
120 Sint32 temp = SignedInt() - (i << IntShift());
122 rep = (temp * -1) | SignMask();
128 Fixed &operator *=(const Fixed &other) {
129 Sint64 temp = SignedInt();
130 temp *= other.SignedInt();
131 temp /= (1 << IntShift());
133 rep = (temp * -1) | SignMask();
139 template<class Scalar>
140 Fixed &operator *=(Scalar i) {
141 Sint32 temp = SignedInt() * i;
143 rep = (temp * -1) | SignMask();
149 Fixed &operator /=(const Fixed &other) {
150 Sint64 temp = SignedInt();
151 temp *= (1 << IntShift());
152 temp /= other.SignedInt();
154 rep = (temp * -1) | SignMask();
160 template<class Scalar>
161 Fixed &operator /=(Scalar i) {
162 Sint32 temp = SignedInt() / i;
164 rep = (temp * -1) | SignMask();
170 Fixed &operator %=(const Fixed &other) {
171 const Uint32 myRaw = RawInt();
172 const Uint32 otherRaw = other.RawInt();
173 const Uint32 intQuotient = myRaw / otherRaw;
174 rep = (myRaw - (otherRaw * intQuotient)) | (rep & SignMask());
177 Fixed &operator %=(int i) {
178 const Uint32 myRaw = RawInt();
179 const Uint32 otherRaw = (i << IntShift());
180 const Uint32 intQuotient = myRaw / otherRaw;
181 rep = (myRaw - (otherRaw * intQuotient)) | (rep & SignMask());
186 int SignBits() const { return 1; }
187 int IntBits() const { return 32 - SignBits() - FracBits(); }
188 int FracBits() const { return fracBits; }
190 int SignShift() const { return 31; }
191 int IntShift() const { return fracBits; }
192 int FracShift() const { return 0; }
194 Uint32 SignMask() const { return 1 << SignShift(); }
195 Uint32 IntMask() const { return ~(SignMask() | FracMask()); }
196 Uint32 FracMask() const { return (1 << IntShift()) - 1; }
198 int SignPart() const { return (rep & SignMask()) >> SignShift(); }
199 int IntPart() const { return (rep & IntMask()) >> IntShift(); }
200 int FracPart() const { return (rep & FracMask()) >> FracShift(); }
202 Sint32 SignedInt() const { return Sigma() * RawInt(); }
203 Uint32 RawInt() const { return rep & (~SignMask()); }
211 template<Uint8 T, Uint8 U>
212 inline bool operator ==(const Fixed<T> &lhs, const Fixed<U> &rhs) {
214 return lhs == Fixed<T>(rhs);
216 return Fixed<U>(lhs) == rhs;
220 template<Uint8 T, Uint8 U>
221 inline bool operator !=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
222 return !(lhs == rhs);
225 template<Uint8 T, Uint8 U>
226 inline bool operator <(const Fixed<T> &lhs, const Fixed<U> &rhs) {
228 return lhs < Fixed<T>(rhs);
230 return Fixed<U>(lhs) < rhs;
234 template<Uint8 T, Uint8 U>
235 inline bool operator <=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
237 return lhs <= Fixed<T>(rhs);
239 return Fixed<U>(lhs) <= rhs;
243 template<Uint8 T, Uint8 U>
244 inline bool operator >(const Fixed<T> &lhs, const Fixed<U> &rhs) {
245 return !(lhs <= rhs);
248 template<Uint8 T, Uint8 U>
249 inline bool operator >=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
253 template<Uint8 T, Uint8 U>
254 inline Fixed<T> operator +(const Fixed<T> &lhs, const Fixed<U> &rhs) {
258 template<Uint8 T, class Other>
259 inline Fixed<T> operator +(const Fixed<T> &lhs, const Other &rhs) {
263 template<Uint8 T, class Other>
264 inline Fixed<T> operator +(const Other &lhs, const Fixed<T> &rhs) {
268 template<Uint8 T, Uint8 U>
269 inline Fixed<T> operator -(const Fixed<T> &lhs, const Fixed<U> &rhs) {
273 template<Uint8 T, class Other>
274 inline Fixed<T> operator -(const Fixed<T> &lhs, const Other &rhs) {
278 template<Uint8 T, class Other>
279 inline Fixed<T> operator -(const Other &lhs, const Fixed<T> &rhs) {
283 template<Uint8 T, Uint8 U>
284 inline Fixed<T> operator *(const Fixed<T> &lhs, const Fixed<U> &rhs) {
288 template<Uint8 T, class Other>
289 inline Fixed<T> operator *(const Fixed<T> &lhs, const Other &rhs) {
293 template<Uint8 T, class Other>
294 inline Fixed<T> operator *(const Other &lhs, const Fixed<T> &rhs) {
298 template<Uint8 T, Uint8 U>
299 inline Fixed<T> operator /(const Fixed<T> &lhs, const Fixed<U> &rhs) {
303 template<Uint8 T, class Other>
304 inline Fixed<T> operator /(const Fixed<T> &lhs, const Other &rhs) {
309 template<Uint8 T, Uint8 U>
310 inline Fixed<T> operator %(const Fixed<T> &lhs, const Fixed<U> &rhs) {
314 template<Uint8 T, class Other>
315 inline Fixed<T> operator %(const Fixed<T> &lhs, const Other &rhs) {
322 inline std::ostream &operator <<(std::ostream &out, const Fixed<T> &f) {
323 return out << f.Double();
331 template <Uint8 fracBits>
332 class numeric_limits<math::Fixed<fracBits> > {
335 static const bool is_specialized = true;
336 static math::Fixed<fracBits> min() throw() {
339 static math::Fixed<fracBits> max() throw() {
340 return math::Fixed<fracBits>(1 << (digits - fracBits) - 1)
341 + math::Fixed<fracBits>((1 << fracBits) - 2, (1 << fracBits) - 1);
343 static const int digits = 31;
344 static const int digits10 = 10;
345 static const bool is_signed = true;
346 static const bool is_integer = false;
347 static const bool is_exact = true;
348 static const int radix = 2;
349 static math::Fixed<fracBits> epsilon() throw() {
350 return math::Fixed<fracBits>(1, 1 << (digits - fracBits) - 1);
352 static math::Fixed<fracBits> round_error() throw() {
356 static const bool is_iec559 = false;
357 static const bool is_bounded = true;
358 static const bool is_modulo = false;
360 static const bool traps = false;
361 static const bool tinyness_before = false;
362 static const float_round_style round_style = round_toward_zero;