2 * ReactOS Calc (RPN encoder/decoder for IEEE-754 engine)
4 * Copyright 2007-2017, Carlo Bramini
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.
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.
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
28 typedef void (*operator_call
)(calc_number_t
*, calc_number_t
*, calc_number_t
*);
37 static stack_node_t
*stack
;
38 static calc_node_t temp
;
39 static BOOL percent_mode
;
41 static void rpn_add_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
42 static void rpn_sub_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
43 static void rpn_mul_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
44 static void rpn_div_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
45 static void rpn_mod_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
46 static void rpn_pow_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
47 static void rpn_sqr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
48 static void rpn_and_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
49 static void rpn_or_f (calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
50 static void rpn_xor_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
51 static void rpn_shl_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
52 static void rpn_shr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
54 /* Integer mode calculations */
55 static void rpn_add_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
56 static void rpn_sub_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
57 static void rpn_mul_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
58 static void rpn_div_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
59 static void rpn_mod_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
60 static void rpn_and_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
61 static void rpn_or_i (calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
62 static void rpn_xor_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
63 static void rpn_shl_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
64 static void rpn_shr_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
66 /* Percentage mode calculations */
67 static void rpn_add_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
68 static void rpn_sub_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
69 static void rpn_mul_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
70 static void rpn_div_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
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
90 static calc_node_t
*pop(void)
108 static int is_stack_empty(void)
110 return (stack
== NULL
);
113 static void push(calc_node_t
*op
)
115 stack_node_t
*z
= (stack_node_t
*)malloc(sizeof(stack_node_t
));
122 static unsigned int get_prec(unsigned int opc)
126 for (x=0; x<SIZEOF(operator_list); x++)
127 if (operator_list[x].opc == opc) break;
128 return operator_list[x].prec;
131 /* Real mode calculations */
132 static void rpn_add_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
137 static void rpn_sub_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
142 static void rpn_mul_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
147 static void rpn_div_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
155 static void rpn_mod_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
163 r
->f
= a
->f
- (t
* b
->f
);
167 static void rpn_and_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
169 calc_number_t ai
, bi
;
171 ai
.i
= logic_dbl2int(a
);
172 bi
.i
= logic_dbl2int(b
);
174 r
->f
= (long double)(ai
.i
& bi
.i
);
177 static void rpn_or_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
179 calc_number_t ai
, bi
;
181 ai
.i
= logic_dbl2int(a
);
182 bi
.i
= logic_dbl2int(b
);
184 r
->f
= (long double)(ai
.i
| bi
.i
);
187 static void rpn_xor_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
189 calc_number_t ai
, bi
;
191 ai
.i
= logic_dbl2int(a
);
192 bi
.i
= logic_dbl2int(b
);
194 r
->f
= (long double)(ai
.i
^ bi
.i
);
197 static void rpn_shl_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
203 r
->f
= a
->f
* pow(2., n
.f
);
206 static void rpn_shr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
212 r
->f
= a
->f
/ pow(2., n
.f
);
215 static void rpn_pow_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
217 r
->f
= pow(a
->f
, b
->f
);
218 if (_finite(r
->f
) == 0 || _isnan(r
->f
))
222 static void rpn_sqr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
227 r
->f
= pow(a
->f
, 1./b
->f
);
228 if (_finite(r
->f
) == 0 || _isnan(r
->f
))
233 /* Integer mode calculations */
234 static void rpn_add_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
239 static void rpn_sub_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
244 static void rpn_mul_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
249 static void rpn_div_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
257 static void rpn_mod_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
265 static void rpn_and_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
270 static void rpn_or_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
275 static void rpn_xor_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
280 static void rpn_shl_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
285 static void rpn_shr_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
290 /* Percent mode calculations */
291 static void rpn_add_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
293 r
->f
= a
->f
* (1. + b
->f
/100.);
296 static void rpn_sub_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
298 r
->f
= a
->f
* (1. - b
->f
/100.);
301 static void rpn_mul_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
303 r
->f
= a
->f
* b
->f
/ 100.;
306 static void rpn_div_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
311 r
->f
= a
->f
* 100. / b
->f
;
314 void run_operator(calc_node_t
*result
,
317 unsigned int operation
)
319 calc_number_t da
, db
, dc
;
320 DWORD base
= calc
.base
;
324 if (a
->base
== IDC_RADIO_DEC
&& b
->base
!= IDC_RADIO_DEC
) {
325 db
.f
= logic_int2dbl(&b
->number
);
326 base
= IDC_RADIO_DEC
;
328 if (a
->base
!= IDC_RADIO_DEC
&& b
->base
== IDC_RADIO_DEC
) {
329 da
.f
= logic_int2dbl(&a
->number
);
330 base
= IDC_RADIO_DEC
;
333 if (base
== IDC_RADIO_DEC
) {
335 percent_mode
= FALSE
;
336 operator_list
[operation
].op_p(&dc
, &da
, &db
);
338 operator_list
[operation
].op_f(&dc
, &da
, &db
);
339 if (_finite(dc
.f
) == 0)
342 operator_list
[operation
].op_i(&dc
, &da
, &db
);
343 /* apply final limiter to result */
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
);
351 if (a
->base
!= IDC_RADIO_DEC
&& b
->base
== IDC_RADIO_DEC
)
352 result
->number
.f
= dc
.f
;
357 static void evalStack(calc_number_t
*number
)
364 prec
= operator_list
[ip
.operation
].prec
;
365 while (!is_stack_empty()) {
368 if (prec
<= operator_list
[op
->operation
].prec
) {
369 if (op
->operation
== RPN_OPERATOR_PARENT
) continue;
371 calc
.prev
= ip
.number
;
372 run_operator(&ip
, op
, &ip
, op
->operation
);
383 if (ip
.operation
!= RPN_OPERATOR_EQUAL
&& ip
.operation
!= RPN_OPERATOR_PERCENT
)
386 calc
.prev_operator
= op
->operation
;
391 int exec_infix2postfix(calc_number_t
*number
, unsigned int func
)
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 */
403 if (func
== RPN_OPERATOR_PERCENT
)
406 tmp
.number
= *number
;
407 tmp
.base
= calc
.base
;
408 tmp
.operation
= func
;
412 if (func
== RPN_OPERATOR_NONE
)
415 if (func
!= RPN_OPERATOR_PARENT
) {
416 calc
.last_operator
= func
;
422 void exec_change_infix(void)
424 stack_node_t
*op
= stack
;
428 if (op
->node
.operation
== RPN_OPERATOR_PARENT
||
429 op
->node
.operation
== RPN_OPERATOR_PERCENT
||
430 op
->node
.operation
== RPN_OPERATOR_EQUAL
)
432 /* remove the head, it will be re-inserted with new operator */
436 void exec_closeparent(calc_number_t
*number
)
442 while (!is_stack_empty()) {
445 if (op
->operation
== RPN_OPERATOR_PARENT
)
448 run_operator(&ip
, op
, &ip
, op
->operation
);
457 int eval_parent_count(void)
459 stack_node_t
*s
= stack
;
463 if (s
->node
.operation
== RPN_OPERATOR_PARENT
)
465 s
= (stack_node_t
*)(s
->next
);
470 void flush_postfix(void)
472 while (!is_stack_empty())
474 /* clear prev and last typed operators */
476 calc
.last_operator
= 0;
479 void start_rpn_engine(void)
484 void stop_rpn_engine(void)