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(); }
54 if (IntPart() == 0 && FracPart() == 0) {
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 Fixed &operator +=(int i) {
100 Sint32 temp = SignedInt() + (i << IntShift());
102 rep = (temp * -1) | SignMask();
108 Fixed &operator -=(const Fixed &other) {
109 Sint32 temp = SignedInt() - other.SignedInt();
111 rep = (temp * -1) | SignMask();
117 Fixed &operator -=(int i) {
118 Sint32 temp = SignedInt() - (i << IntShift());
120 rep = (temp * -1) | SignMask();
126 Fixed &operator *=(const Fixed &other) {
127 Sint64 temp = SignedInt();
128 temp *= other.SignedInt();
129 temp /= (1 << IntShift());
131 rep = (temp * -1) | SignMask();
137 Fixed &operator *=(int i) {
138 Sint32 temp = SignedInt() * i;
140 rep = (temp * -1) | SignMask();
146 Fixed &operator /=(const Fixed &other) {
147 Sint64 temp = SignedInt();
148 temp *= (1 << IntShift());
149 temp /= other.SignedInt();
151 rep = (temp * -1) | SignMask();
157 Fixed &operator /=(int i) {
158 Sint32 temp = SignedInt() / i;
160 rep = (temp * -1) | SignMask();
166 Fixed &operator %=(const Fixed &other) {
167 const Uint32 myRaw = RawInt();
168 const Uint32 otherRaw = other.RawInt();
169 const Uint32 intQuotient = myRaw / otherRaw;
170 rep = (myRaw - (otherRaw * intQuotient)) | (rep & SignMask());
173 Fixed &operator %=(int i) {
174 const Uint32 myRaw = RawInt();
175 const Uint32 otherRaw = (i << IntShift());
176 const Uint32 intQuotient = myRaw / otherRaw;
177 rep = (myRaw - (otherRaw * intQuotient)) | (rep & SignMask());
182 int SignBits() const { return 1; }
183 int IntBits() const { return 32 - SignBits() - FracBits(); }
184 int FracBits() const { return fracBits; }
186 int SignShift() const { return 31; }
187 int IntShift() const { return fracBits; }
188 int FracShift() const { return 0; }
190 Uint32 SignMask() const { return 1 << SignShift(); }
191 Uint32 IntMask() const { return ~(SignMask() | FracMask()); }
192 Uint32 FracMask() const { return (1 << IntShift()) - 1; }
194 int SignPart() const { return (rep & SignMask()) >> SignShift(); }
195 int IntPart() const { return (rep & IntMask()) >> IntShift(); }
196 int FracPart() const { return (rep & FracMask()) >> FracShift(); }
198 Sint32 SignedInt() const { return Sigma() * RawInt(); }
199 Uint32 RawInt() const { return rep & (~SignMask()); }
207 template<Uint8 T, Uint8 U>
208 inline bool operator ==(const Fixed<T> &lhs, const Fixed<U> &rhs) {
210 return lhs == Fixed<T>(rhs);
212 return Fixed<U>(lhs) == rhs;
216 template<Uint8 T, Uint8 U>
217 inline bool operator !=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
218 return !(lhs == rhs);
221 template<Uint8 T, Uint8 U>
222 inline bool operator <(const Fixed<T> &lhs, const Fixed<U> &rhs) {
224 return lhs < Fixed<T>(rhs);
226 return Fixed<U>(lhs) < rhs;
230 template<Uint8 T, Uint8 U>
231 inline bool operator <=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
233 return lhs <= Fixed<T>(rhs);
235 return Fixed<U>(lhs) <= rhs;
239 template<Uint8 T, Uint8 U>
240 inline bool operator >(const Fixed<T> &lhs, const Fixed<U> &rhs) {
241 return !(lhs <= rhs);
244 template<Uint8 T, Uint8 U>
245 inline bool operator >=(const Fixed<T> &lhs, const Fixed<U> &rhs) {
249 template<Uint8 T, Uint8 U>
250 inline Fixed<T> operator +(const Fixed<T> &lhs, const Fixed<U> &rhs) {
254 template<Uint8 T, class Other>
255 inline Fixed<T> operator +(const Fixed<T> &lhs, const Other &rhs) {
259 template<Uint8 T, class Other>
260 inline Fixed<T> operator +(const Other &lhs, const Fixed<T> &rhs) {
264 template<Uint8 T, Uint8 U>
265 inline Fixed<T> operator -(const Fixed<T> &lhs, const Fixed<U> &rhs) {
269 template<Uint8 T, class Other>
270 inline Fixed<T> operator -(const Fixed<T> &lhs, const Other &rhs) {
274 template<Uint8 T, class Other>
275 inline Fixed<T> operator -(const Other &lhs, const Fixed<T> &rhs) {
279 template<Uint8 T, Uint8 U>
280 inline Fixed<T> operator *(const Fixed<T> &lhs, const Fixed<U> &rhs) {
284 template<Uint8 T, class Other>
285 inline Fixed<T> operator *(const Fixed<T> &lhs, const Other &rhs) {
289 template<Uint8 T, class Other>
290 inline Fixed<T> operator *(const Other &lhs, const Fixed<T> &rhs) {
294 template<Uint8 T, Uint8 U>
295 inline Fixed<T> operator /(const Fixed<T> &lhs, const Fixed<U> &rhs) {
299 template<Uint8 T, class Other>
300 inline Fixed<T> operator /(const Fixed<T> &lhs, const Other &rhs) {
305 template<Uint8 T, Uint8 U>
306 inline Fixed<T> operator %(const Fixed<T> &lhs, const Fixed<U> &rhs) {
310 template<Uint8 T, class Other>
311 inline Fixed<T> operator %(const Fixed<T> &lhs, const Other &rhs) {
318 inline std::ostream &operator <<(std::ostream &out, const Fixed<T> &f) {
319 return out << f.Double();
327 template <Uint8 fracBits>
328 class numeric_limits<math::Fixed<fracBits> > {
331 static const bool is_specialized = true;
332 static math::Fixed<fracBits> min() throw() {
335 static math::Fixed<fracBits> max() throw() {
336 return math::Fixed<fracBits>(1 << (digits - fracBits) - 1)
337 + math::Fixed<fracBits>((1 << fracBits) - 2, (1 << fracBits) - 1);
339 static const int digits = 31;
340 static const int digits10 = 10;
341 static const bool is_signed = true;
342 static const bool is_integer = false;
343 static const bool is_exact = true;
344 static const int radix = 2;
345 static math::Fixed<fracBits> epsilon() throw() {
346 return math::Fixed<fracBits>(1, 1 << (digits - fracBits) - 1);
348 static math::Fixed<fracBits> round_error() throw() {
352 static const bool is_iec559 = false;
353 static const bool is_bounded = true;
354 static const bool is_modulo = false;
356 static const bool traps = false;
357 static const bool tinyness_before = false;
358 static const float_round_style round_style = round_toward_zero;