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