1 // bigfix.h
2 //
3 // Copyright (C) 2007-2008, Chris Laurel <claurel@shatters.net>
4 //
5 // 128-bit fixed point (64.64) numbers for high-precision celestial
6 // coordinates. When you need millimeter accurate navigation across a scale
7 // of thousands of light years, double precision floating point numbers
8 // are inadequate.
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14
15 #ifndef _CELUTIL_BIGFIX64_H_
16 #define _CELUTIL_BIGFIX64_H_
17
18 #include <string>
19 #include "basictypes.h"
20
21 /*! 64.64 signed fixed point numbers.
22 */
23
24 class BigFix
25 {
26 public:
27 BigFix();
28 BigFix(uint64);
29 BigFix(double);
30 BigFix(const std::string&);
31
32 operator double() const;
33 operator float() const;
34
35 BigFix operator-() const;
36 BigFix operator+=(const BigFix&);
37 BigFix operator-=(const BigFix&);
38
39 friend BigFix operator+(const BigFix&, const BigFix&);
40 friend BigFix operator-(const BigFix&, const BigFix&);
41 friend BigFix operator*(const BigFix&, const BigFix&);
42 friend BigFix operator*(BigFix, double);
43 friend bool operator==(const BigFix&, const BigFix&);
44 friend bool operator!=(const BigFix&, const BigFix&);
45 friend bool operator<(const BigFix&, const BigFix&);
46 friend bool operator>(const BigFix&, const BigFix&);
47
48 int sign() const;
49
50 // for debugging
51 void dump();
52 std::string toString();
53
54 private:
isNegative()55 bool isNegative() const
56 {
57 return hi > INT64_MAX;
58 }
59
60 static void negate128(uint64& hi, uint64& lo);
61
62 private:
63 uint64 hi;
64 uint64 lo;
65 };
66
67
68 // Compute the additive inverse of a 128-bit twos complement value
69 // represented by two 64-bit values.
negate128(uint64 & hi,uint64 & lo)70 inline void BigFix::negate128(uint64& hi, uint64& lo)
71 {
72 // For a twos-complement number, -n = ~n + 1
73 hi = ~hi;
74 lo = ~lo;
75 lo++;
76 if (lo == 0)
77 hi++;
78 }
79
80 inline BigFix BigFix::operator-() const
81 {
82 BigFix result = *this;
83
84 negate128(result.hi, result.lo);
85
86 return result;
87 }
88
89
90 inline BigFix BigFix::operator+=(const BigFix& a)
91 {
92 lo += a.lo;
93 hi += a.hi;
94
95 // carry
96 if (lo < a.lo)
97 hi++;
98
99 return *this;
100 }
101
102
103 inline BigFix BigFix::operator-=(const BigFix& a)
104 {
105 lo -= a.lo;
106 hi -= a.hi;
107
108 // borrow
109 if (lo > a.lo)
110 hi--;
111
112 return *this;
113 }
114
115
116 inline BigFix operator+(const BigFix& a, const BigFix& b)
117 {
118 BigFix c;
119
120 c.lo = a.lo + b.lo;
121 c.hi = a.hi + b.hi;
122
123 // carry
124 if (c.lo < a.lo)
125 c.hi++;
126
127 return c;
128 }
129
130
131 inline BigFix operator-(const BigFix& a, const BigFix& b)
132 {
133 BigFix c;
134
135 c.lo = a.lo - b.lo;
136 c.hi = a.hi - b.hi;
137
138 // borrow
139 if (c.lo > a.lo)
140 c.hi--;
141
142 return c;
143 }
144
145 #endif // _CELUTIL_BIGFIX64_H_
146