ReactOS 0.4.15-dev-8428-g6910fa6
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
23typedef struct {
25 void *next;
27
29
30typedef struct {
31 unsigned int prec;
36
40
53
54/* Integer mode calculations */
65
66/* Percentage mode calculations */
71
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
90static 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
108static int is_stack_empty(void)
109{
110 return (stack == NULL);
111}
112
113static void push(calc_node_t *op)
114{
116
117 z->node = *op;
118 z->next = stack;
119 stack = z;
120}
121/*
122static 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;
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 */
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) {
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
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
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) {
418 }
419 return 1;
420}
421
423{
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) {
451 return;
452 }
453 }
454 *number = ip.number;
455}
456
458{
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
471{
472 while (!is_stack_empty())
473 pop();
474 /* clear prev and last typed operators */
477}
478
480{
481 stack = NULL;
482}
483
485{
486}
#define IDC_RADIO_DEC
Definition: resource.h:24
operation
Definition: copy.c:29
@ RPN_OPERATOR_NONE
Definition: calc.h:119
@ RPN_OPERATOR_EQUAL
Definition: calc.h:104
@ RPN_OPERATOR_PERCENT
Definition: calc.h:103
@ RPN_OPERATOR_PARENT
Definition: calc.h:102
void apply_int_mask(calc_number_t *a)
Definition: fun_ieee.c:26
double logic_int2dbl(calc_number_t *a)
Definition: fun_ieee.c:275
__int64 logic_dbl2int(calc_number_t *a)
Definition: fun_ieee.c:261
calc_t calc
Definition: winmain.c:247
Definition: _stack.h:55
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
double pow(double x, double y)
Definition: freeldr.c:113
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLdouble GLdouble z
Definition: glext.h:5874
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _isnan(_In_ double)
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _finite(_In_ double)
_Check_return_ _CRTIMP double __cdecl modf(_In_ double x, _Out_ double *y)
static const WCHAR dc[]
static unsigned int number
Definition: dsound.c:1479
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
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_ieee.c:314
void start_rpn_engine(void)
Definition: rpn_ieee.c:479
static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:257
static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:306
static BOOL percent_mode
Definition: rpn_ieee.c:39
static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:296
static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:137
static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:215
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:222
static void rpn_mod_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:155
static const calc_operator_t operator_list[]
Definition: rpn_ieee.c:72
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_shr_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:285
void exec_change_infix(void)
Definition: rpn_ieee.c:422
static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:142
static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:301
void(* operator_call)(calc_number_t *, calc_number_t *, calc_number_t *)
Definition: rpn_ieee.c:28
static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:177
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_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:206
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_xor_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:275
static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:167
static calc_node_t temp
Definition: rpn_ieee.c:38
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_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:197
int eval_parent_count(void)
Definition: rpn_ieee.c:457
static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:132
static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:187
int exec_infix2postfix(calc_number_t *number, unsigned int func)
Definition: rpn_ieee.c:391
static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:147
void exec_closeparent(calc_number_t *number)
Definition: rpn_ieee.c:436
static int is_stack_empty(void)
Definition: rpn_ieee.c:108
static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:291
static void rpn_and_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:265
static void evalStack(calc_number_t *number)
Definition: rpn_ieee.c:357
static stack_node_t * stack
Definition: rpn_ieee.c:37
void stop_rpn_engine(void)
Definition: rpn_ieee.c:484
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113
static void rpn_or_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
Definition: rpn_ieee.c:270
void flush_postfix(void)
Definition: rpn_ieee.c:470
unsigned int operation
Definition: calc.h:134
calc_number_t number
Definition: calc.h:133
DWORD base
Definition: calc.h:135
operator_call op_p
Definition: rpn_ieee.c:34
operator_call op_i
Definition: rpn_ieee.c:33
unsigned int prec
Definition: rpn_ieee.c:31
operator_call op_f
Definition: rpn_ieee.c:32
BOOL sci_in
Definition: calc.h:185
unsigned int prev_operator
Definition: calc.h:198
unsigned int last_operator
Definition: calc.h:197
BOOL is_nan
Definition: calc.h:183
calc_number_t prev
Definition: calc.h:179
DWORD base
Definition: calc.h:189
Definition: dhcpd.h:62
calc_node_t node
Definition: rpn_ieee.c:24
void * next
Definition: rpn_ieee.c:25
INT64 i
Definition: calc.h:127
double f
Definition: calc.h:126