PandA-2024.02
fixedptc.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <stdint.h>
5 #include "fixedptc.h"
6 
7 
8 char str[25] = {0};
9 
10 /* Multiplies two fixedpt numbers, returns the result. */
12 {
13  return (((fixedptd)A * (fixedptd)B) >> FIXEDPT_FBITS);
14 }
15 
16 /* Divides two fixedpt numbers, returns the result. */
18 {
19  return (((fixedptd)A << FIXEDPT_FBITS) / (fixedptd)B);
20 }
21 
22 /*
23  * Note: adding and substracting fixedpt numbers can be done by using
24  * the regular integer operators + and -.
25  */
35 void fixedpt_str(fixedpt A, char *str, int max_dec)
36 {
37  int ndec = 0, slen = 0;
38  char tmp[12] = {0};
39  fixedptud fr, ip;
40  const fixedptud one = (fixedptud)1 << FIXEDPT_BITS;
41  const fixedptud mask = one - 1;
42 
43  if (max_dec == -1)
44 #if FIXEDPT_BITS == 32
45  max_dec = 2;
46 #elif FIXEDPT_BITS == 64
47  max_dec = 10;
48 #else
49 #error Invalid width
50 #endif
51  else if (max_dec == -2)
52  max_dec = 15;
53 
54  if (A < 0) {
55  str[slen++] = '-';
56  A *= -1;
57  }
58 
59  ip = fixedpt_toint(A);
60  do {
61  tmp[ndec++] = '0' + ip % 10;
62  ip /= 10;
63  } while (ip != 0);
64 
65  while (ndec > 0)
66  str[slen++] = tmp[--ndec];
67  str[slen++] = '.';
68 
69  // printf("before shift left %x\n", fr);
70  fr = (fixedpt_fracpart(A) << FIXEDPT_WBITS) & mask;
71 // printf("before iter %x\n", fr);
72  do {
73  fr = (fr & mask) * 10;
74  // printf("iter %x\n", fr);
75  str[slen++] = '0' + (fr >> FIXEDPT_BITS) % 10;
76  // printf("char %c\n", '0' + (fr >> FIXEDPT_BITS) % 10);
77  ndec++;
78  } while (fr != 0 && ndec < max_dec);
79 
80  if (ndec > 1 && str[slen - 1] == '0')
81  str[slen - 1] = '\0'; /* cut off trailing 0 */
82  else
83  str[slen] = '\0';
84 }
85 
86 /* Converts the given fixedpt number into a string, using a static
87  * (non-threadsafe) string buffer */
88 char * fixedpt_cstr(const fixedpt A, const int max_dec)
89 {
90 
91  fixedpt_str(A, str, max_dec);
92  return (str);
93 }
94 
95 /* Returns the square root of the given number, or -1 in case of error */
97 {
98  int invert = 0;
99  int iter = FIXEDPT_FBITS;
100 
101  if (A < 0)
102  return (-1);
103  if (A == 0 || A == FIXEDPT_ONE)
104  return (A);
105  if (A < FIXEDPT_ONE && A > 6) {
106  invert = 1;
107  A = fixedpt_div(FIXEDPT_ONE, A);
108  }
109  if (A > FIXEDPT_ONE) {
110  int s = A;
111 
112  iter = 0;
113  while (s > 0) {
114  s >>= 2;
115  iter++;
116  }
117  }
118 
119  /* Newton's iterations */
120  int l = (A >> 1) + 1;
121  for (int i = 0; i < iter; i++)
122  l = (l + fixedpt_div(A, l)) >> 1;
123  if (invert)
124  return (fixedpt_div(FIXEDPT_ONE, l));
125  return (l);
126 }
127 
128 /* Returns the sine of the given fixedpt number.
129  * Note: the loss of precision is extraordinary! */
131 {
132  int sign = 1;
133  fixedpt sqr, result;
134  const fixedpt SK[2] = {
135  fixedpt_rconst(7.61e-03),
136  fixedpt_rconst(1.6605e-01)
137  };
138 
139  fp %= 2 * FIXEDPT_PI;
140  if (fp < 0)
141  fp = FIXEDPT_PI * 2 + fp;
142  if ((fp > FIXEDPT_HALF_PI) && (fp <= FIXEDPT_PI))
143  fp = FIXEDPT_PI - fp;
144  else if ((fp > FIXEDPT_PI) && (fp <= (FIXEDPT_PI + FIXEDPT_HALF_PI))) {
145  fp = fp - FIXEDPT_PI;
146  sign = -1;
147  } else if (fp > (FIXEDPT_PI + FIXEDPT_HALF_PI)) {
148  fp = (FIXEDPT_PI << 1) - fp;
149  sign = -1;
150  }
151  sqr = fixedpt_mul(fp, fp);
152  result = SK[0];
153  result = fixedpt_mul(result, sqr);
154  result -= SK[1];
155  result = fixedpt_mul(result, sqr);
156  result += FIXEDPT_ONE;
157  result = fixedpt_mul(result, fp);
158  return sign * result;
159 }
160 
161 /* Returns the cosine of the given fixedpt number */
163 {
164  return (fixedpt_sin(FIXEDPT_HALF_PI - A));
165 }
166 
167 /* Returns the tangens of the given fixedpt number */
169 {
170  return fixedpt_div(fixedpt_sin(A), fixedpt_cos(A));
171 }
172 
173 /* Returns the value exp(x), i.e. e^x of the given fixedpt number. */
175 {
176  fixedpt xabs, k, z, R, xp, ans;
177  const fixedpt LN2 = fixedpt_rconst(0.69314718055994530942);
178  const fixedpt LN2_INV = fixedpt_rconst(1.4426950408889634074);
179  const fixedpt EXP_P[5] = {
180  fixedpt_rconst(1.66666666666666019037e-01),
181  fixedpt_rconst(-2.77777777770155933842e-03),
182  fixedpt_rconst(6.61375632143793436117e-05),
183  fixedpt_rconst(-1.65339022054652515390e-06),
184  fixedpt_rconst(4.13813679705723846039e-08),
185  };
186 
187  if (fp == 0) {
188 // printf("excuted fp = 0 ");
189  return (FIXEDPT_ONE);
190  }
191 
192 
193  xabs = fixedpt_abs(fp);
194 // printf("xabs = fixedpt_abs(fp); = ");
195 // fixedpt_print(xabs);
196 
197  k = fixedpt_mul(xabs, LN2_INV);
198  //switch the exponents to base 2
199  //now calculating 2^k
200 // printf("k = fixedpt_mul(xabs, LN2_INV); = ");
201 // fixedpt_print(k);
202 
203  k += FIXEDPT_ONE_HALF;
204 // printf("k += FIXEDPT_ONE_HALF; = ");
205 // fixedpt_print(k);
206 
207  k &= ~FIXEDPT_FMASK;
208 // printf("k &= ~FIXEDPT_FMASK; = ");
209 // fixedpt_print(k);
210 
211  if (fp < 0) {
212  k = -k;
213 // printf("k = -k; = ");
214 // fixedpt_print(k);
215  }
216 
217  fp -= fixedpt_mul(k, LN2);
218 // printf("fp -= fixedpt_mul(k, LN2);");
219 // fixedpt_print(fp);
220 
221  z = fixedpt_mul(fp, fp);
222 // printf("z = fixedpt_mul(fp, fp); = ");
223 // fixedpt_print(z);
224 
225 
226  /* Taylor */
227  R = FIXEDPT_TWO +
228  fixedpt_mul(z, EXP_P[0] + fixedpt_mul(z, EXP_P[1] +
229  fixedpt_mul(z, EXP_P[2] + fixedpt_mul(z, EXP_P[3] +
230  fixedpt_mul(z, EXP_P[4])))));
231 // printf("R = FIXEDPT_TWO +"
232 // "fixedpt_mul(z, EXP_P[0] + fixedpt_mul(z, EXP_P[1] +"
233 // "fixedpt_mul(z, EXP_P[2] + fixedpt_mul(z, EXP_P[3] +"
234 // "fixedpt_mul(z, EXP_P[4])))));= ");
235 // fixedpt_print(R);
236 
237 
238  xp = FIXEDPT_ONE + fixedpt_div(fixedpt_mul(fp, FIXEDPT_TWO), R - fp);
239 // printf("xp = FIXEDPT_ONE + fixedpt_div(fixedpt_mul(fp, FIXEDPT_TWO), R - fp); ");
240 // fixedpt_print(xp);
241 
242 
243  if (k < 0) {
244  k = FIXEDPT_ONE >> (-k >> FIXEDPT_FBITS);
245 // printf("k = FIXEDPT_ONE >> (-k >> FIXEDPT_FBITS);");
246 // fixedpt_print(k);
247  } else {
248  k = FIXEDPT_ONE << (k >> FIXEDPT_FBITS);
249 // printf("k = FIXEDPT_ONE << (k >> FIXEDPT_FBITS);");
250 // fixedpt_print(k);
251  }
252  ans = fixedpt_mul(k, xp);
253 // printf("ans = fixedpt_mul(k, xp)");
254 // fixedpt_print(ans);
255  return (ans);
256 }
257 
258 /* Returns the natural logarithm of the given fixedpt number. */
260 {
261  fixedpt log2, xi;
262  fixedpt f, s, z, w, R;
263  const fixedpt LN2 = fixedpt_rconst(0.69314718055994530942);
264  const fixedpt LG[7] = {
265  fixedpt_rconst(6.666666666666735130e-01),
266  fixedpt_rconst(3.999999999940941908e-01),
267  fixedpt_rconst(2.857142874366239149e-01),
268  fixedpt_rconst(2.222219843214978396e-01),
269  fixedpt_rconst(1.818357216161805012e-01),
270  fixedpt_rconst(1.531383769920937332e-01),
271  fixedpt_rconst(1.479819860511658591e-01)
272  };
273 
274  if (x < 0)
275  return (0);
276  if (x == 0)
277  return 0xffffffff;
278 
279  log2 = 0;
280  xi = x;
281  while (xi > FIXEDPT_TWO) {
282  xi >>= 1;
283  log2++;
284  }
285  f = xi - FIXEDPT_ONE;
286  s = fixedpt_div(f, FIXEDPT_TWO + f);
287  z = fixedpt_mul(s, s);
288  w = fixedpt_mul(z, z);
289  R = fixedpt_mul(w, LG[1] + fixedpt_mul(w, LG[3]
290  + fixedpt_mul(w, LG[5]))) + fixedpt_mul(z, LG[0]
291  + fixedpt_mul(w, LG[2] + fixedpt_mul(w, LG[4]
292  + fixedpt_mul(w, LG[6]))));
293  return (fixedpt_mul(LN2, (log2 << FIXEDPT_FBITS)) + f
294  - fixedpt_mul(s, f - R));
295 }
296 
297 /* Returns the logarithm of the given base of the given fixedpt number */
299 {
300  return (fixedpt_div(fixedpt_ln(x), fixedpt_ln(base)));
301 }
302 
303 /* Return the power value (n^exp) of the given fixedpt numbers */
305 {
306  if (exp == 0)
307  return (FIXEDPT_ONE);
308  if (n < 0)
309  return 0;
310  return (fixedpt_exp(fixedpt_mul(fixedpt_ln(n), exp)));
311 }
fixedpt fixedpt_sqrt(fixedpt A)
Definition: fixedptc.c:96
#define FIXEDPT_FBITS
Definition: fixedptc.h:104
char base
This version is stamped on May 10, 2016.
Definition: nussinov.c:24
void fixedpt_str(fixedpt A, char *str, int max_dec)
Convert the given fixedpt number to a decimal string.
Definition: fixedptc.c:35
#define R
Definition: mips.c:40
fixedpt fixedpt_log(fixedpt x, fixedpt base)
Definition: fixedptc.c:298
#define FIXEDPT_ONE_HALF
Definition: fixedptc.h:119
fixedpt fixedpt_pow(fixedpt n, fixedpt exp)
Definition: fixedptc.c:304
#define FIXEDPT_BITS
Definition: fixedptc.h:75
fixedpt fixedpt_ln(fixedpt x)
Definition: fixedptc.c:259
#define fixedpt_toint(F)
Definition: fixedptc.h:109
#define A
Definition: generate.c:13
#define FIXEDPT_TWO
Definition: fixedptc.h:120
#define FIXEDPT_PI
Definition: fixedptc.h:121
#define FIXEDPT_FMASK
Definition: fixedptc.h:105
static const uint32_t k[]
Definition: sha-256.c:22
fixedpt fixedpt_tan(fixedpt A)
Definition: fixedptc.c:168
fixedpt fixedpt_exp(fixedpt fp)
Definition: fixedptc.c:174
#define fixedpt_fracpart(A)
Definition: fixedptc.h:116
fixedpt fixedpt_mul(fixedpt A, fixedpt B)
Definition: fixedptc.c:11
fixedpt fixedpt_sin(fixedpt fp)
Definition: fixedptc.c:130
fixedpt fixedpt_div(fixedpt A, fixedpt B)
Definition: fixedptc.c:17
int result[SIZE]
Definition: adpcm.c:800
char * fixedpt_cstr(const fixedpt A, const int max_dec)
Definition: fixedptc.c:88
fixedpt fixedpt_cos(fixedpt A)
Definition: fixedptc.c:162
int64_t fixedptd
Definition: fixedptc.h:80
char str[25]
Definition: fixedptc.c:8
uint64_t fixedptud
Definition: fixedptc.h:82
#define fixedpt_rconst(R)
Definition: fixedptc.h:107
uint32_t sign
x
Return the smallest n such that 2^n >= _x.
#define FIXEDPT_ONE
Definition: fixedptc.h:118
#define fixedpt_abs(A)
Definition: fixedptc.h:126
#define B
Definition: generate.c:14
int32_t fixedpt
Definition: fixedptc.h:79
uint32_t exp
#define FIXEDPT_HALF_PI
Definition: fixedptc.h:123
#define FIXEDPT_WBITS
Definition: fixedptc.h:95

Generated on Mon Feb 12 2024 13:02:49 for PandA-2024.02 by doxygen 1.8.13