ReactOS  0.4.13-dev-257-gfabbd7c
rpn_mpfr.c
Go to the documentation of this file.
1 /*
2  * ReactOS Calc (RPN encoder/decoder for GMP/MPFR engine)
3  *
4  * Copyright 2007-2017, Carlo Bramini
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "calc.h"
22 
23 typedef struct {
25  void *next;
26 } stack_node_t;
27 
29 
30 typedef struct {
31  unsigned int prec;
32  operator_call op_f;
33  operator_call op_i;
34  operator_call op_p;
36 
40 
52 
53 /* Integer mode calculations */
59 
60 /* Percentage mode calculations */
65 
66 static const calc_operator_t operator_list[] = {
67  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_PARENT
68  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_PERCENT
69  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_EQUAL
70  { 1, rpn_or_f, rpn_or_f, NULL, }, // RPN_OPERATOR_OR
71  { 2, rpn_xor_f, rpn_xor_f, NULL, }, // RPN_OPERATOR_XOR
72  { 3, rpn_and_f, rpn_and_f, NULL, }, // RPN_OPERATOR_AND
73  { 4, rpn_shl_f, rpn_shl_f, NULL, }, // RPN_OPERATOR_LSH
74  { 4, rpn_shr_f, rpn_shr_f, NULL, }, // RPN_OPERATOR_RSH
75  { 5, rpn_add_f, rpn_add_i, rpn_add_p, }, // RPN_OPERATOR_ADD
76  { 5, rpn_sub_f, rpn_sub_i, rpn_sub_p, }, // RPN_OPERATOR_SUB
77  { 6, rpn_mul_f, rpn_mul_i, rpn_mul_p, }, // RPN_OPERATOR_MULT
78  { 6, rpn_div_f, rpn_div_i, rpn_div_p, }, // RPN_OPERATOR_DIV
79  { 6, rpn_mod_i, rpn_mod_i, NULL, }, // RPN_OPERATOR_MOD
80  { 7, rpn_pow_f, NULL, NULL, }, // RPN_OPERATOR_POW
81  { 7, rpn_sqr_f, NULL, NULL, }, // RPN_OPERATOR_SQR
82 };
83 
85 {
86  mpfr_set(dst->number.mf, src->number.mf, MPFR_DEFAULT_RND);
87  dst->operation = src->operation;
88 }
89 
90 static calc_node_t *pop(void)
91 {
92  void *next;
93 
94  if (stack == NULL)
95  return NULL;
96 
97  /* copy the node */
98  node_copy(&temp, &stack->node);
99  next = stack->next;
100 
101  /* free the node */
102  mpfr_clear(stack->node.number.mf);
103  free(stack);
104  stack = next;
105 
106  return &temp;
107 }
108 
109 static int is_stack_empty(void)
110 {
111  return (stack == NULL);
112 }
113 
114 static void push(calc_node_t *op)
115 {
117 
118  mpfr_init_set(z->node.number.mf, op->number.mf, MPFR_DEFAULT_RND);
119  z->node.operation = op->operation;
120  z->next = stack;
121  stack = z;
122 }
123 /*
124 static unsigned int get_prec(unsigned int opc)
125 {
126  unsigned int x;
127 
128  for (x=0; x<SIZEOF(operator_list); x++)
129  if (operator_list[x].opc == opc) break;
130  return operator_list[x].prec;
131 }
132 */
133 
134 typedef void (*exec_call_t)
135 __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
136 
137 static void rpn_exec_int(calc_number_t *r, calc_number_t *a, calc_number_t *b, exec_call_t cb)
138 {
139  mpz_t ai, bi;
140 
141  mpz_init(ai);
142  mpz_init(bi);
143  mpfr_get_z(ai, a->mf, MPFR_DEFAULT_RND);
144  mpfr_get_z(bi, b->mf, MPFR_DEFAULT_RND);
145  cb(ai, ai, bi);
146  mpfr_set_z(r->mf, ai, MPFR_DEFAULT_RND);
147  mpz_clear(ai);
148  mpz_clear(bi);
149 }
150 
151 
152 /* Real mode calculations */
154 {
155  mpfr_add(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
156 }
157 
159 {
160  mpfr_sub(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
161 }
162 
164 {
165  mpfr_mul(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
166 }
167 
169 {
170  if (mpfr_sgn(b->mf) == 0)
171  calc.is_nan = TRUE;
172  else
173  mpfr_div(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
174 }
175 
177 {
178  rpn_exec_int(r, a, b, mpz_and);
179 }
180 
182 {
183  rpn_exec_int(r, a, b, mpz_ior);
184 }
185 
187 {
188  rpn_exec_int(r, a, b, mpz_xor);
189 }
190 
192 {
193  unsigned long e;
194 
195  mpfr_trunc(r->mf, b->mf);
196  if (mpfr_fits_ulong_p(r->mf, MPFR_DEFAULT_RND) == 0)
197  calc.is_nan = TRUE;
198  else {
199  e = mpfr_get_ui(r->mf, MPFR_DEFAULT_RND);
200  mpfr_mul_2exp(r->mf, a->mf, e, MPFR_DEFAULT_RND);
201  }
202 }
203 
205 {
206  unsigned long e;
207 
208  mpfr_trunc(r->mf, b->mf);
209  if (mpfr_fits_ulong_p(r->mf, MPFR_DEFAULT_RND) == 0)
210  calc.is_nan = TRUE;
211  else {
212  e = mpfr_get_ui(r->mf, MPFR_DEFAULT_RND);
213  mpfr_div_2exp(r->mf, a->mf, e, MPFR_DEFAULT_RND);
214  }
215 }
216 
218 {
219  mpfr_pow(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
220 }
221 
223 {
224  if (mpfr_sgn(b->mf) == 0)
225  calc.is_nan = TRUE;
226  else {
227  mpfr_t tmp;
228 
229  mpfr_init(tmp);
230  mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
231  mpfr_ui_div(tmp, 1, tmp, MPFR_DEFAULT_RND);
232  mpfr_pow(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
233  mpfr_clear(tmp);
234  }
235 }
236 
237 /* Integer mode calculations */
239 {
240  rpn_exec_int(r, a, b, mpz_add);
241 }
242 
244 {
245  rpn_exec_int(r, a, b, mpz_sub);
246 }
247 
249 {
250  rpn_exec_int(r, a, b, mpz_mul);
251 }
252 
254 {
255  if (mpfr_sgn(b->mf) == 0)
256  calc.is_nan = TRUE;
257  else
258  rpn_exec_int(r, a, b, mpz_tdiv_q);
259 }
260 
262 {
263  if (mpfr_sgn(b->mf) == 0)
264  calc.is_nan = TRUE;
265  else
266  rpn_exec_int(r, a, b, mpz_tdiv_r);
267 }
268 
269 /* Percent mode calculations */
271 {
272  mpfr_t tmp;
273 
274  mpfr_init(tmp);
275  mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
276  mpfr_div_ui(tmp, tmp, 100, MPFR_DEFAULT_RND);
277  mpfr_add_ui(tmp, tmp, 1, MPFR_DEFAULT_RND);
278  mpfr_mul(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
279  mpfr_clear(tmp);
280 }
281 
283 {
284  mpfr_t tmp;
285 
286  mpfr_init(tmp);
287  mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
288  mpfr_div_ui(tmp, tmp, 100, MPFR_DEFAULT_RND);
289  mpfr_sub_ui(tmp, tmp, 1, MPFR_DEFAULT_RND);
290  mpfr_mul(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
291  mpfr_clear(tmp);
292 }
293 
295 {
296  mpfr_mul(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
297  mpfr_div_ui(r->mf, r->mf, 100, MPFR_DEFAULT_RND);
298 }
299 
301 {
302  if (mpfr_sgn(b->mf) == 0)
303  calc.is_nan = TRUE;
304  else {
305  mpfr_mul_ui(r->mf, a->mf, 100, MPFR_DEFAULT_RND);
306  mpfr_div(r->mf, r->mf, b->mf, MPFR_DEFAULT_RND);
307  }
308 }
309 
311  calc_node_t *a,
312  calc_node_t *b,
313  unsigned int operation)
314 {
315  if (calc.base == IDC_RADIO_DEC) {
316  if (percent_mode) {
318  operator_list[operation].op_p(&result->number, &a->number, &b->number);
319  } else
320  operator_list[operation].op_f(&result->number, &a->number, &b->number);
321  } else {
322  operator_list[operation].op_i(&result->number, &a->number, &b->number);
323  /* apply final limiter to result */
324  apply_int_mask(&result->number);
325  }
326 }
327 
329 {
330  calc_node_t *op, ip;
331  unsigned int prec;
332 
333  mpfr_init(ip.number.mf);
334  op = pop();
335  node_copy(&ip, op);
336  prec = operator_list[ip.operation].prec;
337  while (!is_stack_empty()) {
338  op = pop();
339 
340  if (prec <= operator_list[op->operation].prec) {
341  if (op->operation == RPN_OPERATOR_PARENT) continue;
342 
343  rpn_copy(&calc.prev, &ip.number);
344  run_operator(&ip, op, &ip, op->operation);
345  if (calc.is_nan) {
346  flush_postfix();
347  mpfr_clear(ip.number.mf);
348  return;
349  }
350  } else {
351  push(op);
352  break;
353  }
354  }
355 
356  if (ip.operation != RPN_OPERATOR_EQUAL && ip.operation != RPN_OPERATOR_PERCENT)
357  push(&ip);
358 
359  calc.prev_operator = op->operation;
360 
361  rpn_copy(number, &ip.number);
362  mpfr_clear(ip.number.mf);
363 }
364 
366 {
367  calc_node_t tmp;
368 
369  if (is_stack_empty() && func == RPN_OPERATOR_EQUAL) {
370  /* if a number has been entered with exponential */
371  /* notation, I may update it with normal mode */
372  if (calc.sci_in)
373  return 1;
374  return 0;
375  }
376 
377  if (func == RPN_OPERATOR_PERCENT)
378  percent_mode = TRUE;
379 
380  mpfr_init(tmp.number.mf);
381  rpn_copy(&tmp.number, number);
382  tmp.operation = func;
383 
384  push(&tmp);
385  mpfr_clear(tmp.number.mf);
386 
387  if (func == RPN_OPERATOR_NONE)
388  return 0;
389 
390  if (func != RPN_OPERATOR_PARENT) {
392  evalStack(number);
393  }
394  return 1;
395 }
396 
398 {
399  stack_node_t *op = stack;
400 
401  if (op == NULL)
402  return;
403  if (op->node.operation == RPN_OPERATOR_PARENT ||
404  op->node.operation == RPN_OPERATOR_PERCENT ||
405  op->node.operation == RPN_OPERATOR_EQUAL)
406  return;
407  /* remove the head, it will be re-inserted with new operator */
408  pop();
409 }
410 
412 {
413  calc_node_t *op, ip;
414 
415  rpn_alloc(&ip.number);
416  rpn_copy(&ip.number, number);
417  while (!is_stack_empty()) {
418  op = pop();
419 
420  if (op->operation == RPN_OPERATOR_PARENT)
421  break;
422 
423  run_operator(&ip, op, &ip, op->operation);
424  if (calc.is_nan) {
425  flush_postfix();
426  return;
427  }
428  }
429  rpn_copy(number, &ip.number);
430  rpn_free(&ip.number);
431 }
432 
434 {
435  stack_node_t *s = stack;
436  int n = 0;
437 
438  while (s != NULL) {
439  if (s->node.operation == RPN_OPERATOR_PARENT)
440  n++;
441  s = (stack_node_t *)(s->next);
442  }
443  return n;
444 }
445 
446 void flush_postfix(void)
447 {
448  while (!is_stack_empty())
449  pop();
450  /* clear prev and last typed operators */
452  calc.last_operator = 0;
453 }
454 
456 {
457  mpf_set_default_prec(512);
458  mpfr_set_default_prec(512);
459  stack = NULL;
460  mpfr_init(calc.code.mf);
461  mpfr_init(calc.prev.mf);
462  mpfr_init(calc.memory.number.mf);
463  mpfr_init(temp.number.mf);
465 }
466 
467 void stop_rpn_engine(void)
468 {
469  mpfr_clear(calc.code.mf);
470  mpfr_clear(calc.prev.mf);
471  mpfr_clear(calc.memory.number.mf);
472  mpfr_clear(temp.number.mf);
473 }
GLenum func
Definition: glext.h:6028
static const calc_operator_t operator_list[]
Definition: rpn_mpfr.c:66
static calc_node_t temp
Definition: rpn_mpfr.c:38
DWORD base
Definition: calc.h:189
static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:217
#define TRUE
Definition: types.h:120
void rpn_copy(calc_number_t *dst, calc_number_t *src)
Definition: fun_ieee.c:591
void(* operator_call)(calc_number_t *, calc_number_t *, calc_number_t *)
Definition: rpn_mpfr.c:28
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
calc_number_t code
Definition: calc.h:178
#define IDC_RADIO_DEC
Definition: resource.h:22
static void node_copy(calc_node_t *dst, calc_node_t *src)
Definition: rpn_mpfr.c:84
static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:163
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define free
Definition: debug_ros.c:5
void rpn_zero(calc_number_t *c)
Definition: fun_ieee.c:586
void rpn_free(calc_number_t *c)
Definition: fun_ieee.c:605
static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:191
GLdouble n
Definition: glext.h:7729
static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:153
static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:261
BOOL is_nan
Definition: calc.h:183
static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:222
void flush_postfix(void)
Definition: rpn_mpfr.c:446
static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:158
static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:238
struct node node
unsigned int BOOL
Definition: ntddk_ex.h:94
#define e
Definition: ke_i.h:82
static size_t double number
Definition: printf.c:64
int ip[4]
Definition: rtl.c:1176
GLdouble GLdouble z
Definition: glext.h:5874
smooth NULL
Definition: ftsmooth.c:416
static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:270
unsigned int prec
Definition: rpn_ieee.c:31
unsigned int prev_operator
Definition: calc.h:198
int exec_infix2postfix(calc_number_t *number, unsigned int func)
Definition: rpn_mpfr.c:365
static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:181
static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:253
static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:294
static void evalStack(calc_number_t *number)
Definition: rpn_mpfr.c:328
Definition: _stack.h:47
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
static BOOL percent_mode
Definition: rpn_mpfr.c:39
Definition: dhcpd.h:61
void start_rpn_engine(void)
Definition: rpn_mpfr.c:455
static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:243
static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:282
BOOL sci_in
Definition: calc.h:185
unsigned int last_operator
Definition: calc.h:197
static DWORD cb
Definition: integrity.c:41
static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:204
calc_number_t number
Definition: calc.h:133
operator_call op_f
Definition: rpn_ieee.c:32
static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:186
GLdouble s
Definition: gl.h:2039
GLenum src
Definition: glext.h:6340
void exec_call_t __GMP_PROTO((mpz_ptr, mpz_srcptr, mpz_srcptr))
Definition: rpn_mpfr.c:135
static unsigned __int64 next
Definition: rand_nt.c:6
void run_operator(calc_node_t *result, calc_node_t *a, calc_node_t *b, unsigned int operation)
Definition: rpn_mpfr.c:310
static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:248
GLenum GLenum dst
Definition: glext.h:6340
static void push(calc_node_t *op)
Definition: rpn_mpfr.c:114
unsigned int operation
Definition: calc.h:134
static void rpn_exec_int(calc_number_t *r, calc_number_t *a, calc_number_t *b, exec_call_t cb)
Definition: rpn_mpfr.c:137
operator_call op_i
Definition: rpn_ieee.c:33
static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:300
#define malloc
Definition: debug_ros.c:4
static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:176
calc_node_t memory
Definition: calc.h:180
UINT op
Definition: effect.c:223
operator_call op_p
Definition: rpn_ieee.c:34
void exec_closeparent(calc_number_t *number)
Definition: rpn_mpfr.c:411
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
void exec_change_infix(void)
Definition: rpn_mpfr.c:397
static int is_stack_empty(void)
Definition: rpn_mpfr.c:109
calc_t calc
Definition: winmain.c:247
int eval_parent_count(void)
Definition: rpn_mpfr.c:433
GLuint64EXT * result
Definition: glext.h:11304
static stack_node_t * stack
Definition: rpn_mpfr.c:37
static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_mpfr.c:168
void stop_rpn_engine(void)
Definition: rpn_mpfr.c:467
calc_number_t prev
Definition: calc.h:179
void apply_int_mask(calc_number_t *a)
Definition: fun_ieee.c:26
static calc_node_t * pop(void)
Definition: rpn_mpfr.c:90
void rpn_alloc(calc_number_t *c)
Definition: fun_ieee.c:601