ReactOS  0.4.14-dev-593-g1793dcc
rpn_ieee.c
Go to the documentation of this file.
1 /*
2  * ReactOS Calc (RPN encoder/decoder for IEEE-754 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;
36 
40 
53 
54 /* Integer mode calculations */
65 
66 /* Percentage mode calculations */
71 
72 static const calc_operator_t operator_list[] = {
73  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_PARENT
74  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_PERCENT
75  { 0, NULL, NULL, NULL, }, // RPN_OPERATOR_EQUAL
76  { 1, rpn_or_f, rpn_or_i, NULL, }, // RPN_OPERATOR_OR
77  { 2, rpn_xor_f, rpn_xor_i, NULL, }, // RPN_OPERATOR_XOR
78  { 3, rpn_and_f, rpn_and_i, NULL, }, // RPN_OPERATOR_AND
79  { 4, rpn_shl_f, rpn_shl_i, NULL, }, // RPN_OPERATOR_LSH
80  { 4, rpn_shr_f, rpn_shr_i, NULL, }, // RPN_OPERATOR_RSH
81  { 5, rpn_add_f, rpn_add_i, rpn_add_p, }, // RPN_OPERATOR_ADD
82  { 5, rpn_sub_f, rpn_sub_i, rpn_sub_p, }, // RPN_OPERATOR_SUB
83  { 6, rpn_mul_f, rpn_mul_i, rpn_mul_p, }, // RPN_OPERATOR_MULT
84  { 6, rpn_div_f, rpn_div_i, rpn_div_p, }, // RPN_OPERATOR_DIV
85  { 6, rpn_mod_f, rpn_mod_i, NULL, }, // RPN_OPERATOR_MOD
86  { 7, rpn_pow_f, NULL, NULL, }, // RPN_OPERATOR_POW
87  { 7, rpn_sqr_f, NULL, NULL, }, // RPN_OPERATOR_SQR
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  temp = stack->node;
99  next = stack->next;
100 
101  /* free the node */
102  free(stack);
103  stack = next;
104 
105  return &temp;
106 }
107 
108 static int is_stack_empty(void)
109 {
110  return (stack == NULL);
111 }
112 
113 static void push(calc_node_t *op)
114 {
116 
117  z->node = *op;
118  z->next = stack;
119  stack = z;
120 }
121 /*
122 static unsigned int get_prec(unsigned int opc)
123 {
124  unsigned int x;
125 
126  for (x=0; x<SIZEOF(operator_list); x++)
127  if (operator_list[x].opc == opc) break;
128  return operator_list[x].prec;
129 }
130 */
131 /* Real mode calculations */
133 {
134  r->f = a->f + b->f;
135 }
136 
138 {
139  r->f = a->f - b->f;
140 }
141 
143 {
144  r->f = a->f * b->f;
145 }
146 
148 {
149  if (b->f == 0)
150  calc.is_nan = TRUE;
151  else
152  r->f = a->f / b->f;
153 }
154 
156 {
157  double t;
158 
159  if (b->f == 0)
160  calc.is_nan = TRUE;
161  else {
162  modf(a->f/b->f, &t);
163  r->f = a->f - (t * b->f);
164  }
165 }
166 
168 {
169  calc_number_t ai, bi;
170 
171  ai.i = logic_dbl2int(a);
172  bi.i = logic_dbl2int(b);
173 
174  r->f = (long double)(ai.i & bi.i);
175 }
176 
178 {
179  calc_number_t ai, bi;
180 
181  ai.i = logic_dbl2int(a);
182  bi.i = logic_dbl2int(b);
183 
184  r->f = (long double)(ai.i | bi.i);
185 }
186 
188 {
189  calc_number_t ai, bi;
190 
191  ai.i = logic_dbl2int(a);
192  bi.i = logic_dbl2int(b);
193 
194  r->f = (long double)(ai.i ^ bi.i);
195 }
196 
198 {
200 
201  modf(b->f, &n.f);
202 
203  r->f = a->f * pow(2., n.f);
204 }
205 
207 {
209 
210  modf(b->f, &n.f);
211 
212  r->f = a->f / pow(2., n.f);
213 }
214 
216 {
217  r->f = pow(a->f, b->f);
218  if (_finite(r->f) == 0 || _isnan(r->f))
219  calc.is_nan = TRUE;
220 }
221 
223 {
224  if (b->f == 0)
225  calc.is_nan = TRUE;
226  else {
227  r->f = pow(a->f, 1./b->f);
228  if (_finite(r->f) == 0 || _isnan(r->f))
229  calc.is_nan = TRUE;
230  }
231 }
232 
233 /* Integer mode calculations */
235 {
236  r->i = a->i + b->i;
237 }
238 
240 {
241  r->i = a->i - b->i;
242 }
243 
245 {
246  r->i = a->i * b->i;
247 }
248 
250 {
251  if (b->i == 0)
252  calc.is_nan = TRUE;
253  else
254  r->i = a->i / b->i;
255 }
256 
258 {
259  if (b->i == 0)
260  calc.is_nan = TRUE;
261  else
262  r->i = a->i % b->i;
263 }
264 
266 {
267  r->i = a->i & b->i;
268 }
269 
271 {
272  r->i = a->i | b->i;
273 }
274 
276 {
277  r->i = a->i ^ b->i;
278 }
279 
281 {
282  r->i = a->i << b->i;
283 }
284 
286 {
287  r->i = a->i >> b->i;
288 }
289 
290 /* Percent mode calculations */
292 {
293  r->f = a->f * (1. + b->f/100.);
294 }
295 
297 {
298  r->f = a->f * (1. - b->f/100.);
299 }
300 
302 {
303  r->f = a->f * b->f / 100.;
304 }
305 
307 {
308  if (b->f == 0)
309  calc.is_nan = TRUE;
310  else
311  r->f = a->f * 100. / b->f;
312 }
313 
315  calc_node_t *a,
316  calc_node_t *b,
317  unsigned int operation)
318 {
319  calc_number_t da, db, dc;
320  DWORD base = calc.base;
321 
322  da = a->number;
323  db = b->number;
324  if (a->base == IDC_RADIO_DEC && b->base != IDC_RADIO_DEC) {
325  db.f = logic_int2dbl(&b->number);
327  } else
328  if (a->base != IDC_RADIO_DEC && b->base == IDC_RADIO_DEC) {
329  da.f = logic_int2dbl(&a->number);
331  }
332 
333  if (base == IDC_RADIO_DEC) {
334  if (percent_mode) {
336  operator_list[operation].op_p(&dc, &da, &db);
337  } else
338  operator_list[operation].op_f(&dc, &da, &db);
339  if (_finite(dc.f) == 0)
340  calc.is_nan = TRUE;
341  } else {
342  operator_list[operation].op_i(&dc, &da, &db);
343  /* apply final limiter to result */
344  apply_int_mask(&dc);
345  }
346 
347  if (a->base == IDC_RADIO_DEC && b->base != IDC_RADIO_DEC) {
348  result->number.i = logic_dbl2int(&dc);
349  apply_int_mask(&result->number);
350  } else
351  if (a->base != IDC_RADIO_DEC && b->base == IDC_RADIO_DEC)
352  result->number.f = dc.f;
353  else
354  result->number = dc;
355 }
356 
358 {
359  calc_node_t *op, ip;
360  unsigned int prec;
361 
362  op = pop();
363  ip = *op;
364  prec = operator_list[ip.operation].prec;
365  while (!is_stack_empty()) {
366  op = pop();
367 
368  if (prec <= operator_list[op->operation].prec) {
369  if (op->operation == RPN_OPERATOR_PARENT) continue;
370 
371  calc.prev = ip.number;
372  run_operator(&ip, op, &ip, op->operation);
373  if (calc.is_nan) {
374  flush_postfix();
375  return;
376  }
377  } else {
378  push(op);
379  break;
380  }
381  }
382 
383  if (ip.operation != RPN_OPERATOR_EQUAL && ip.operation != RPN_OPERATOR_PERCENT)
384  push(&ip);
385 
386  calc.prev_operator = op->operation;
387 
388  *number = ip.number;
389 }
390 
392 {
393  calc_node_t tmp;
394 
395  if (is_stack_empty() && func == RPN_OPERATOR_EQUAL) {
396  /* if a number has been entered with exponential */
397  /* notation, I may update it with normal mode */
398  if (calc.sci_in)
399  return 1;
400  return 0;
401  }
402 
403  if (func == RPN_OPERATOR_PERCENT)
404  percent_mode = TRUE;
405 
406  tmp.number = *number;
407  tmp.base = calc.base;
408  tmp.operation = func;
409 
410  push(&tmp);
411 
412  if (func == RPN_OPERATOR_NONE)
413  return 0;
414 
415  if (func != RPN_OPERATOR_PARENT) {
417  evalStack(number);
418  }
419  return 1;
420 }
421 
423 {
424  stack_node_t *op = stack;
425 
426  if (op == NULL)
427  return;
428  if (op->node.operation == RPN_OPERATOR_PARENT ||
429  op->node.operation == RPN_OPERATOR_PERCENT ||
430  op->node.operation == RPN_OPERATOR_EQUAL)
431  return;
432  /* remove the head, it will be re-inserted with new operator */
433  pop();
434 }
435 
437 {
438  calc_node_t *op, ip;
439 
440  ip.number = *number;
441  ip.base = calc.base;
442  while (!is_stack_empty()) {
443  op = pop();
444 
445  if (op->operation == RPN_OPERATOR_PARENT)
446  break;
447 
448  run_operator(&ip, op, &ip, op->operation);
449  if (calc.is_nan) {
450  flush_postfix();
451  return;
452  }
453  }
454  *number = ip.number;
455 }
456 
458 {
459  stack_node_t *s = stack;
460  int n = 0;
461 
462  while (s != NULL) {
463  if (s->node.operation == RPN_OPERATOR_PARENT)
464  n++;
465  s = (stack_node_t *)(s->next);
466  }
467  return n;
468 }
469 
470 void flush_postfix(void)
471 {
472  while (!is_stack_empty())
473  pop();
474  /* clear prev and last typed operators */
476  calc.last_operator = 0;
477 }
478 
480 {
481  stack = NULL;
482 }
483 
484 void stop_rpn_engine(void)
485 {
486 }
static void evalStack(calc_number_t *number)
Definition: rpn_ieee.c:357
GLenum func
Definition: glext.h:6028
static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:257
DWORD base
Definition: calc.h:189
#define TRUE
Definition: types.h:120
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _isnan(_In_ double)
static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:296
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define IDC_RADIO_DEC
Definition: resource.h:22
static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:239
static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:301
static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:222
double f
Definition: calc.h:126
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define free
Definition: debug_ros.c:5
void(* operator_call)(calc_number_t *, calc_number_t *, calc_number_t *)
Definition: rpn_ieee.c:28
static void rpn_xor_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:275
int eval_parent_count(void)
Definition: rpn_ieee.c:457
GLdouble n
Definition: glext.h:7729
static void rpn_or_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:270
GLdouble GLdouble t
Definition: gl.h:2047
static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:249
static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:234
static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:244
static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:167
static stack_node_t * stack
Definition: rpn_ieee.c:37
double logic_int2dbl(calc_number_t *a)
Definition: fun_ieee.c:275
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
BOOL is_nan
Definition: calc.h:183
static void rpn_mod_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:155
__int64 logic_dbl2int(calc_number_t *a)
Definition: fun_ieee.c:261
static void rpn_shl_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:280
static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:147
unsigned int BOOL
Definition: ntddk_ex.h:94
float pow(float __x, int __y)
Definition: _cmath.h:458
static size_t double number
Definition: printf.c:69
int ip[4]
Definition: rtl.c:1176
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
GLdouble GLdouble z
Definition: glext.h:5874
smooth NULL
Definition: ftsmooth.c:416
unsigned int prec
Definition: rpn_ieee.c:31
unsigned int prev_operator
Definition: calc.h:198
static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:187
static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:197
Definition: _stack.h:47
static const calc_operator_t operator_list[]
Definition: rpn_ieee.c:72
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
Definition: dhcpd.h:61
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _finite(_In_ double)
void stop_rpn_engine(void)
Definition: rpn_ieee.c:484
static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:206
INT64 i
Definition: calc.h:127
void exec_closeparent(calc_number_t *number)
Definition: rpn_ieee.c:436
void run_operator(calc_node_t *result, calc_node_t *a, calc_node_t *b, unsigned int operation)
Definition: rpn_ieee.c:314
int exec_infix2postfix(calc_number_t *number, unsigned int func)
Definition: rpn_ieee.c:391
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL sci_in
Definition: calc.h:185
unsigned int last_operator
Definition: calc.h:197
calc_number_t number
Definition: calc.h:133
static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:132
operator_call op_f
Definition: rpn_ieee.c:32
static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:142
GLdouble s
Definition: gl.h:2039
static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:291
calc_node_t node
Definition: rpn_ieee.c:24
static int is_stack_empty(void)
Definition: rpn_ieee.c:108
static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:306
static unsigned __int64 next
Definition: rand_nt.c:6
static calc_node_t temp
Definition: rpn_ieee.c:38
DWORD base
Definition: calc.h:135
void exec_change_infix(void)
Definition: rpn_ieee.c:422
static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:177
unsigned int operation
Definition: calc.h:134
static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:215
operator_call op_i
Definition: rpn_ieee.c:33
static void rpn_shr_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:285
static const WCHAR dc[]
#define malloc
Definition: debug_ros.c:4
UINT op
Definition: effect.c:223
operator_call op_p
Definition: rpn_ieee.c:34
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
static void rpn_and_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:265
static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:137
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113
void * next
Definition: rpn_ieee.c:25
calc_t calc
Definition: winmain.c:247
GLuint64EXT * result
Definition: glext.h:11304
void start_rpn_engine(void)
Definition: rpn_ieee.c:479
void flush_postfix(void)
Definition: rpn_ieee.c:470
calc_number_t prev
Definition: calc.h:179
void apply_int_mask(calc_number_t *a)
Definition: fun_ieee.c:26
static BOOL percent_mode
Definition: rpn_ieee.c:39
_Check_return_ _CRTIMP double __cdecl modf(_In_ double x, _Out_ double *y)