MFMv2.0.10
Movable Feast Machine Simulator 2.0.10
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FXP.h
1 /* -*- C++ -*- */
40 #ifndef _FXP_H
41 #define _FXP_H
42 
43 #ifndef FXP_STDIO
44 #define FXP_STDIO 1
45 #endif
46 
47 #if FXP_STDIO
48 #include <stdio.h> /* For FILE */
49 #endif
50 
51 #include "itype.h"
52 
53 namespace MFM {
54 
55  // The template argument p in all of the following functions refers to the
56  // fixed point precision (e.g. p = 8 gives 24.8 fixed point functions).
57 
58  // Perform a fixed point multiplication without a 64-bit intermediate result.
59  // This is fast but beware of overflow!
60  template <int p>
61  inline s32 fixmulf(s32 a, s32 b)
62  {
63  return (a * b) >> p;
64  }
65 
66  // Perform a fixed point multiplication using a 64-bit intermediate result to
67  // prevent overflow problems.
68  template <int p>
69  inline s32 fixmul(s32 a, s32 b)
70  {
71  return (s32)(((int64_t)a * b) >> p);
72  }
73 
74  // Fixed point division
75  template <int p>
76  inline int fixdiv(s32 a, s32 b)
77  {
78 #if 1
79  return (s32)((((s64)a) << p) / b);
80 #else
81  // The following produces the same results as the above but gcc 4.0.3
82  // generates fewer instructions (at least on the ARM processor).
83  union {
84  s64 a;
85  struct {
86  s32 l;
87  s32 h;
88  } halves;
89  } x;
90 
91  x.halves.l = a << p;
92  x.halves.h = a >> (sizeof(s32) * 8 - p);
93  return (s32)(x.a / b);
94 #endif
95  }
96 
97  namespace detail {
98  inline u32 CountLeadingZeros(u32 x)
99  {
100  u32 exp = 31;
101 
102  if (x & 0xffff0000) {
103  exp -= 16;
104  x >>= 16;
105  }
106 
107  if (x & 0xff00) {
108  exp -= 8;
109  x >>= 8;
110  }
111 
112  if (x & 0xf0) {
113  exp -= 4;
114  x >>= 4;
115  }
116 
117  if (x & 0xc) {
118  exp -= 2;
119  x >>= 2;
120  }
121 
122  if (x & 0x2) {
123  exp -= 1;
124  }
125 
126  return exp;
127  }
128  }
129 
130  // q is the precision of the input
131  // output has 32-q bits of fraction
132  template <int q>
133  inline int fixinv(s32 a)
134  {
135  s32 x;
136 
137  bool sign = false;
138 
139  if (a < 0) {
140  sign = true;
141  a = -a;
142  }
143 
144  static const uint16_t rcp_tab[] = {
145  0x8000, 0x71c7, 0x6666, 0x5d17, 0x5555, 0x4ec4, 0x4924, 0x4444
146  };
147 
148  s32 exp = detail::CountLeadingZeros(a);
149  x = ((s32)rcp_tab[(a>>(28-exp))&0x7]) << 2;
150  exp -= 16;
151 
152  if (exp <= 0)
153  x >>= -exp;
154  else
155  x <<= exp;
156 
157  /* two iterations of newton-raphson x = x(2-ax) */
158  x = fixmul<(32-q)>(x,((2<<(32-q)) - fixmul<q>(a,x)));
159  x = fixmul<(32-q)>(x,((2<<(32-q)) - fixmul<q>(a,x)));
160 
161  if (sign)
162  return -x;
163  else
164  return x;
165  }
166 
167  // Conversion from and to float
168 
169  template <int p>
170  float fix2float(s32 f)
171  {
172  return (float)f / (1 << p);
173  }
174 
175  template <int p>
176  s32 float2fix(float f)
177  {
178  return (s32)(f * (1 << p));
179  }
180 
181  s32 fixcos16(s32 a);
182  s32 fixsin16(s32 a);
183  s32 fixrsqrt16(s32 a);
184  s32 fixsqrt16(s32 a);
185 
186  // The template argument p in all of the following functions refers to the
187  // fixed point precision (e.g. p = 8 gives 24.8 fixed point functions).
188 
189  template <int p>
190  struct FXP {
191  s32 intValue;
192 
193  FXP() : intValue(0) {}
194  /*explicit*/ FXP(u32 i) : intValue(i << p) {}
195  /*explicit*/ FXP(s32 i) : intValue(i << p) {}
196  /*explicit*/ FXP(float f) : intValue(float2fix<p>(f)) {}
197  /*explicit*/ FXP(double f) : intValue(float2fix<p>((float)f)) {}
198 
199  FXP& operator += (FXP r) { intValue += r.intValue; return *this; }
200  FXP& operator -= (FXP r) { intValue -= r.intValue; return *this; }
201  FXP& operator *= (FXP r) { intValue = fixmul<p>(intValue, r.intValue); return *this; }
202  FXP& operator /= (FXP r) { intValue = fixdiv<p>(intValue, r.intValue); return *this; }
203 
204  FXP& operator ++ () { *this += 1; return *this; }
205  FXP operator ++ (int) { const FXP val = *this; ++ *this; return val; }
206 
207  FXP& operator -- () { *this -= 1; return *this; }
208  FXP operator -- (int) { const FXP val = *this; -- *this; return val; }
209 
210  FXP& operator *= (s32 r) { intValue *= r; return *this; }
211  FXP& operator /= (s32 r) { intValue /= r; return *this; }
212 
213  FXP operator - () const { FXP x; x.intValue = -intValue; return x; }
214  FXP operator + (FXP r) const { FXP x = *this; x += r; return x;}
215  FXP operator - (FXP r) const { FXP x = *this; x -= r; return x;}
216  FXP operator * (FXP r) const { FXP x = *this; x *= r; return x;}
217  FXP operator / (FXP r) const { FXP x = *this; x /= r; return x;}
218 
219  bool operator == (FXP r) const { return intValue == r.intValue; }
220  bool operator != (FXP r) const { return !(*this == r); }
221  bool operator < (FXP r) const { return intValue < r.intValue; }
222  bool operator > (FXP r) const { return intValue > r.intValue; }
223  bool operator <= (FXP r) const { return intValue <= r.intValue; }
224  bool operator >= (FXP r) const { return intValue >= r.intValue; }
225 
226  FXP operator + (s32 r) const { FXP x = *this; x += r; return x;}
227  FXP operator - (s32 r) const { FXP x = *this; x -= r; return x;}
228  FXP operator * (s32 r) const { FXP x = *this; x *= r; return x;}
229  FXP operator / (s32 r) const { FXP x = *this; x /= r; return x;}
230 
231  s32 asInt() const { return intValue; }
232  float toFloat() const { return fix2float<p>(intValue); }
233  double toDouble() const { return (double) fix2float<p>(intValue); }
234 
235 #if FXP_STDIO
236  void Print(FILE * f) {
237  u32 val;
238  if (intValue < 0) {
239  val = -intValue;
240  fputc('-',f);
241  } else val = intValue;
242  fprintf(f,"%d.", val >> p);
243  for (int i = 0; i < "011122233344445556667777888999:::"[p]-'0'; ++i) {
244  val &= (1<<p)-1;
245  val *= 10;
246  fputc((val>>p)+'0',f);
247  }
248  }
249 #endif
250 
251  };
252 
253  typedef FXP<16> FXP16;
254 
255  // Specializations for use with plain integers
256  template <int p>
257  inline FXP<p> operator + (s32 a, FXP<p> b)
258  { return b + a; }
259 
260  template <int p>
261  inline FXP<p> operator - (s32 a, FXP<p> b)
262  { return -b + a; }
263 
264  template <int p>
265  inline FXP<p> operator * (s32 a, FXP<p> b)
266  { return b * a; }
267 
268  template <int p>
269  inline FXP<p> operator / (s32 a, FXP<p> b)
270  { FXP<p> r(a); r /= b; return r; }
271 
272  // math functions
273  // no default implementation
274 
275  template <int p>
276  inline FXP<p> Sin(FXP<p> a);
277 
278  template <int p>
279  inline FXP<p> Cos(FXP<p> a);
280 
281  template <int p>
282  inline FXP<p> Sqrt(FXP<p> a);
283 
284  template <int p>
285  inline FXP<p> Rsqrt(FXP<p> a);
286 
287  template <int p>
288  inline FXP<p> Inv(FXP<p> a);
289 
290  template <int p>
291  inline FXP<p> Abs(FXP<p> a)
292  {
293  FXP<p> r;
294  r.intValue = a.intValue > 0 ? a.intValue : -a.intValue;
295  return r;
296  }
297 
298  // specializations for 16.16 format
299 
300  template <>
301  inline FXP<16> Sin(FXP<16> a)
302  {
303  FXP<16> r;
304  r.intValue = fixsin16(a.intValue);
305  return r;
306  }
307 
308  template <>
309  inline FXP<16> Cos(FXP<16> a)
310  {
311  FXP<16> r;
312  r.intValue = fixcos16(a.intValue);
313  return r;
314  }
315 
316 
317  template <>
318  inline FXP<16> Sqrt(FXP<16> a)
319  {
320  FXP<16> r;
321  r.intValue = fixsqrt16(a.intValue);
322  return r;
323  }
324 
325  template <>
326  inline FXP<16> Rsqrt(FXP<16> a)
327  {
328  FXP<16> r;
329  r.intValue = fixrsqrt16(a.intValue);
330  return r;
331  }
332 
333  template <>
334  inline FXP<16> Inv(FXP<16> a)
335  {
336  FXP<16> r;
337  r.intValue = fixinv<16>(a.intValue);
338  return r;
339  }
340 
341  // The multiply accumulate case can be optimized.
342  template <int p>
343  inline FXP<p> multiply_accumulate(
344  int count,
345  const FXP<p> *a,
346  const FXP<p> *b)
347  {
348  s64 result = 0;
349  for (int i = 0; i < count; ++i)
350  result += static_cast<s64>(a[i].intValue) * b[i].intValue;
351  FXP<p> r;
352  r.intValue = static_cast<s32>(result >> p);
353  return r;
354  }
355 
356 
357 } // end namespace MFM
358 
359 #endif /* _FXP_H */
360 
Definition: FXP.h:190