Pioneer
fixed.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _FIXED_H
5 #define _FIXED_H
6 
7 #include <SDL_stdinc.h>
8 #include <cassert>
9 
10 template <int FRAC_BITS>
11 class fixedf {
12 public:
13  static const int FRAC = FRAC_BITS;
14  static const Uint64 MASK = (Uint64(1UL) << FRAC_BITS) - 1;
15 
16  fixedf() :
17  v(0) {}
18  // template <int bits>
19  // fixedf(fixedf<bits> f) { *this = f; }
20  constexpr fixedf(Sint64 raw) :
21  v(raw) {}
22  constexpr fixedf(Sint64 num, Sint64 denom) :
23  v((num << FRAC) / denom) {}
24  // ^^ this is fucking shit
25 
26  fixedf Abs() const { return fixedf(v >= 0 ? v : -v); }
27  friend fixedf operator+(const fixedf &a, const Sint64 b) { return a + fixedf(b << FRAC); }
28  friend fixedf operator-(const fixedf &a, const Sint64 b) { return a - fixedf(b << FRAC); }
29  friend fixedf operator*(const fixedf &a, const Sint64 b) { return a * fixedf(b << FRAC); }
30  friend fixedf operator/(const fixedf &a, const Sint64 b) { return a / fixedf(b << FRAC); }
31  friend fixedf operator+(const Sint64 a, const fixedf &b) { return fixedf(a << FRAC) + b; }
32  friend fixedf operator-(const Sint64 a, const fixedf &b) { return fixedf(a << FRAC) - b; }
33  friend fixedf operator*(const Sint64 a, const fixedf &b) { return fixedf(a << FRAC) * b; }
34  friend fixedf operator/(const Sint64 a, const fixedf &b) { return fixedf(a << FRAC) / b; }
35  friend bool operator==(const fixedf &a, const Sint64 b) { return a == fixedf(b << FRAC); }
36  friend bool operator==(const Sint64 a, const fixedf &b) { return b == fixedf(a << FRAC); }
37  friend bool operator!=(const fixedf &a, const Sint64 b) { return a != fixedf(b << FRAC); }
38  friend bool operator!=(const Sint64 a, const fixedf &b) { return b != fixedf(a << FRAC); }
39  friend bool operator>=(const fixedf &a, const Sint64 b) { return a >= fixedf(b << FRAC); }
40  friend bool operator>=(const Sint64 a, const fixedf &b) { return b >= fixedf(a << FRAC); }
41  friend bool operator<=(const fixedf &a, const Sint64 b) { return a <= fixedf(b << FRAC); }
42  friend bool operator<=(const Sint64 a, const fixedf &b) { return b <= fixedf(a << FRAC); }
43  friend bool operator>(const fixedf &a, const Sint64 b) { return a > fixedf(b << FRAC); }
44  friend bool operator>(const Sint64 a, const fixedf &b) { return b > fixedf(a << FRAC); }
45  friend bool operator<(const fixedf &a, const Sint64 b) { return a < fixedf(b << FRAC); }
46  friend bool operator<(const Sint64 a, const fixedf &b) { return b < fixedf(a << FRAC); }
47  friend fixedf operator>>(const fixedf &a, const int b) { return fixedf(a.v >> b); }
48  friend fixedf operator<<(const fixedf &a, const int b) { return fixedf(a.v << b); }
49 
51  {
52  (*this) = (*this) * a;
53  return (*this);
54  }
55  fixedf &operator*=(const Sint64 a)
56  {
57  (*this) = (*this) * a;
58  return (*this);
59  }
61  {
62  (*this) = (*this) / a;
63  return (*this);
64  }
65  fixedf &operator/=(const Sint64 a)
66  {
67  (*this) = (*this) / a;
68  return (*this);
69  }
71  {
72  (*this) = (*this) + a;
73  return (*this);
74  }
75  fixedf &operator+=(const Sint64 a)
76  {
77  (*this) = (*this) + a;
78  return (*this);
79  }
81  {
82  (*this) = (*this) - a;
83  return (*this);
84  }
85  fixedf &operator-=(const Sint64 a)
86  {
87  (*this) = (*this) - a;
88  return (*this);
89  }
90  fixedf &operator>>=(const int a)
91  {
92  v >>= a;
93  return (*this);
94  }
95  fixedf &operator<<=(const int a)
96  {
97  v <<= a;
98  return (*this);
99  }
100 
101  friend fixedf operator-(const fixedf &a) { return fixedf(-a.v); }
102  friend fixedf operator+(const fixedf &a, const fixedf &b) { return fixedf(a.v + b.v); }
103  friend fixedf operator-(const fixedf &a, const fixedf &b) { return fixedf(a.v - b.v); }
104  friend fixedf operator*(const fixedf &a, const fixedf &b)
105  {
106  // 64*64 = (128bit>>FRAC) & ((1<<64)-1)
107  //return fixedf(a.v*b.v >> FRAC);
108  Sint64 hi = 0;
109  Uint64 a0, a1, b0, b1;
110  Uint64 lo = 0;
111  Uint64 oldlo;
112  int isneg = 0;
113  if (a.v < 0) {
114  a0 = (-a.v) & 0xffffffff;
115  a1 = (-a.v) >> 32;
116  isneg = !isneg;
117  } else {
118  a0 = a.v & 0xffffffff;
119  a1 = a.v >> 32;
120  }
121  if (b.v < 0) {
122  b0 = (-b.v) & 0xffffffff;
123  b1 = (-b.v) >> 32;
124  isneg = !isneg;
125  } else {
126  b0 = b.v & 0xffffffff;
127  b1 = b.v >> 32;
128  }
129  Uint64 x;
130  // a0 * b;
131  lo = a0 * b0;
132  oldlo = lo;
133  x = a0 * b1;
134  lo += x << 32;
135  if (lo < oldlo) hi++;
136  oldlo = lo;
137  hi += (x >> 32);
138 
139  // a1 * b;
140  x = a1 * b0;
141  lo += x << 32;
142  if (lo < oldlo) hi++;
143  oldlo = lo;
144  hi += x >> 32;
145 
146  hi += a1 * b1;
147  Sint64 out = (lo >> FRAC) + ((hi & MASK) << (64 - FRAC));
148  return isneg ? -out : out;
149  }
150  friend fixedf operator/(const fixedf &a, const fixedf &b)
151  {
152  // 128-bit divided by 64-bit, to make sure high bits are not lost
153  Sint64 quotient_hi = a.v >> (64 - FRAC);
154  Uint64 quotient_lo = a.v << FRAC;
155  Sint64 d = b.v;
156  int isneg = 0;
157  Sint64 remainder = 0;
158 
159  if (d < 0) {
160  d = -d;
161  isneg = 1;
162  }
163 
164  for (int i = 0; i < 128; i++) {
165  Uint64 sbit = (Uint64(1) << 63) & quotient_hi;
166  remainder <<= 1;
167  if (sbit) remainder |= 1;
168  // shift quotient left 1
169  {
170  quotient_hi <<= 1;
171  if (quotient_lo & (Uint64(1) << 63)) quotient_hi |= 1;
172  quotient_lo <<= 1;
173  }
174  if (remainder >= d) {
175  remainder -= d;
176  quotient_lo |= 1;
177  }
178  }
179  return (isneg ? -Sint64(quotient_lo) : quotient_lo);
180  }
181  friend bool operator==(const fixedf &a, const fixedf &b) { return a.v == b.v; }
182  friend bool operator!=(const fixedf &a, const fixedf &b) { return a.v != b.v; }
183  friend bool operator>(const fixedf &a, const fixedf &b) { return a.v > b.v; }
184  friend bool operator<(const fixedf &a, const fixedf &b) { return a.v < b.v; }
185  friend bool operator>=(const fixedf &a, const fixedf &b) { return a.v >= b.v; }
186  friend bool operator<=(const fixedf &a, const fixedf &b) { return a.v <= b.v; }
187 
188  /* implicit operator float() bad */
189  inline int ToInt32() const { return int(v >> FRAC); }
190  inline Sint64 ToInt64() const { return v >> FRAC; }
191  inline float ToFloat() const { return v / float(Sint64(1) << FRAC); }
192  inline double ToDouble() const { return v / double(Sint64(1) << FRAC); }
193 
194  static fixedf FromDouble(const double val) { return fixedf(Sint64(((val) * double(Sint64(1) << FRAC)))); }
195 
196  template <int NEW_FRAC_BITS>
197  operator fixedf<NEW_FRAC_BITS>() const
198  {
199  int shift = NEW_FRAC_BITS - FRAC_BITS;
200  if (shift > 0)
201  return fixedf<NEW_FRAC_BITS>(v << shift);
202  else
203  return fixedf<NEW_FRAC_BITS>(v >> (-shift));
204  }
205 
206  static fixedf SqrtOf(const fixedf &a)
207  {
208  /* only works on even-numbered fractional bits */
209  assert(!(FRAC & 1));
210  Uint64 root, remHi, remLo, testDiv, count;
211  root = 0;
212  remHi = 0;
213  remLo = a.v;
214  count = 32 + (FRAC >> 1) - 1;
215  do {
216  remHi = (remHi << 2) | (remLo >> 62);
217  remLo <<= 2;
218  root <<= 1;
219  testDiv = (root << 1) + 1;
220  if (remHi >= testDiv) {
221  remHi -= testDiv;
222  root++;
223  }
224  } while (count-- != 0);
225 
226  return (fixedf(root));
227  }
228 
229  static fixedf CubeRootOf(const fixedf &a)
230  {
231  /* NR method. XXX very bad initial estimate (we get there in
232  * the end... XXX */
233  fixedf x = a;
234  for (int i = 0; i < 48; i++)
235  x = fixedf(1, 3) * ((a / (x * x)) + 2 * x);
236  return x;
237  }
238 
239  Sint64 v;
240 };
241 
243 
244 #endif /* _FIXED_H */
double val
Definition: PrecalcPath.cpp:40
Definition: fixed.h:11
static fixedf CubeRootOf(const fixedf &a)
Definition: fixed.h:229
friend fixedf operator+(const fixedf &a, const fixedf &b)
Definition: fixed.h:102
friend bool operator<=(const Sint64 a, const fixedf &b)
Definition: fixed.h:42
friend fixedf operator+(const Sint64 a, const fixedf &b)
Definition: fixed.h:31
fixedf & operator-=(const Sint64 a)
Definition: fixed.h:85
friend fixedf operator<<(const fixedf &a, const int b)
Definition: fixed.h:48
friend fixedf operator/(const Sint64 a, const fixedf &b)
Definition: fixed.h:34
fixedf & operator>>=(const int a)
Definition: fixed.h:90
Sint64 v
Definition: fixed.h:239
fixedf & operator/=(const Sint64 a)
Definition: fixed.h:65
static fixedf SqrtOf(const fixedf &a)
Definition: fixed.h:206
friend fixedf operator/(const fixedf &a, const Sint64 b)
Definition: fixed.h:30
int ToInt32() const
Definition: fixed.h:189
friend bool operator>=(const fixedf &a, const Sint64 b)
Definition: fixed.h:39
friend bool operator<(const fixedf &a, const fixedf &b)
Definition: fixed.h:184
friend bool operator!=(const fixedf &a, const fixedf &b)
Definition: fixed.h:182
friend fixedf operator-(const fixedf &a)
Definition: fixed.h:101
friend bool operator>(const fixedf &a, const Sint64 b)
Definition: fixed.h:43
constexpr fixedf(Sint64 raw)
Definition: fixed.h:20
fixedf & operator*=(const Sint64 a)
Definition: fixed.h:55
friend bool operator<(const Sint64 a, const fixedf &b)
Definition: fixed.h:46
friend bool operator<=(const fixedf &a, const Sint64 b)
Definition: fixed.h:41
friend bool operator==(const fixedf &a, const Sint64 b)
Definition: fixed.h:35
friend fixedf operator-(const Sint64 a, const fixedf &b)
Definition: fixed.h:32
friend fixedf operator>>(const fixedf &a, const int b)
Definition: fixed.h:47
friend bool operator==(const fixedf &a, const fixedf &b)
Definition: fixed.h:181
friend bool operator==(const Sint64 a, const fixedf &b)
Definition: fixed.h:36
fixedf Abs() const
Definition: fixed.h:26
fixedf & operator+=(const Sint64 a)
Definition: fixed.h:75
friend fixedf operator/(const fixedf &a, const fixedf &b)
Definition: fixed.h:150
fixedf & operator+=(const fixedf &a)
Definition: fixed.h:70
float ToFloat() const
Definition: fixed.h:191
fixedf()
Definition: fixed.h:16
static fixedf FromDouble(const double val)
Definition: fixed.h:194
friend fixedf operator-(const fixedf &a, const fixedf &b)
Definition: fixed.h:103
static const Uint64 MASK
Definition: fixed.h:14
friend bool operator>(const Sint64 a, const fixedf &b)
Definition: fixed.h:44
friend fixedf operator+(const fixedf &a, const Sint64 b)
Definition: fixed.h:27
constexpr fixedf(Sint64 num, Sint64 denom)
Definition: fixed.h:22
fixedf & operator<<=(const int a)
Definition: fixed.h:95
friend fixedf operator*(const Sint64 a, const fixedf &b)
Definition: fixed.h:33
friend fixedf operator*(const fixedf &a, const fixedf &b)
Definition: fixed.h:104
friend bool operator!=(const fixedf &a, const Sint64 b)
Definition: fixed.h:37
friend bool operator>=(const fixedf &a, const fixedf &b)
Definition: fixed.h:185
static const int FRAC
Definition: fixed.h:13
friend bool operator!=(const Sint64 a, const fixedf &b)
Definition: fixed.h:38
fixedf & operator-=(const fixedf &a)
Definition: fixed.h:80
friend fixedf operator-(const fixedf &a, const Sint64 b)
Definition: fixed.h:28
friend bool operator>=(const Sint64 a, const fixedf &b)
Definition: fixed.h:40
fixedf & operator*=(const fixedf &a)
Definition: fixed.h:50
Sint64 ToInt64() const
Definition: fixed.h:190
fixedf & operator/=(const fixedf &a)
Definition: fixed.h:60
friend bool operator<(const fixedf &a, const Sint64 b)
Definition: fixed.h:45
friend bool operator<=(const fixedf &a, const fixedf &b)
Definition: fixed.h:186
friend bool operator>(const fixedf &a, const fixedf &b)
Definition: fixed.h:183
friend fixedf operator*(const fixedf &a, const Sint64 b)
Definition: fixed.h:29
double ToDouble() const
Definition: fixed.h:192
fixedf< 32 > fixed
Definition: fixed.h:242