2 * ReactOS Calc (RPN encoder/decoder for GMP/MPFR 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_pow_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
46 static void rpn_sqr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
47 static void rpn_and_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
48 static void rpn_or_f (calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
49 static void rpn_xor_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
50 static void rpn_shl_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
51 static void rpn_shr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
53 /* Integer mode calculations */
54 static void rpn_add_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
55 static void rpn_sub_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
56 static void rpn_mul_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
57 static void rpn_div_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
58 static void rpn_mod_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
60 /* Percentage mode calculations */
61 static void rpn_add_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
62 static void rpn_sub_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
63 static void rpn_mul_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
64 static void rpn_div_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
);
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
84 static void node_copy(calc_node_t
*dst
, calc_node_t
*src
)
86 mpfr_set(dst
->number
.mf
, src
->number
.mf
, MPFR_DEFAULT_RND
);
87 dst
->operation
= src
->operation
;
90 static calc_node_t
*pop(void)
98 node_copy(&temp
, &stack
->node
);
102 mpfr_clear(stack
->node
.number
.mf
);
109 static int is_stack_empty(void)
111 return (stack
== NULL
);
114 static void push(calc_node_t
*op
)
116 stack_node_t
*z
= (stack_node_t
*)malloc(sizeof(stack_node_t
));
118 mpfr_init_set(z
->node
.number
.mf
, op
->number
.mf
, MPFR_DEFAULT_RND
);
119 z
->node
.operation
= op
->operation
;
124 static unsigned int get_prec(unsigned int opc)
128 for (x=0; x<SIZEOF(operator_list); x++)
129 if (operator_list[x].opc == opc) break;
130 return operator_list[x].prec;
134 typedef void (*exec_call_t
)
135 __GMP_PROTO ((mpz_ptr
, mpz_srcptr
, mpz_srcptr
));
137 static void rpn_exec_int(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
, exec_call_t cb
)
143 mpfr_get_z(ai
, a
->mf
, MPFR_DEFAULT_RND
);
144 mpfr_get_z(bi
, b
->mf
, MPFR_DEFAULT_RND
);
146 mpfr_set_z(r
->mf
, ai
, MPFR_DEFAULT_RND
);
152 /* Real mode calculations */
153 static void rpn_add_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
155 mpfr_add(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
158 static void rpn_sub_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
160 mpfr_sub(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
163 static void rpn_mul_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
165 mpfr_mul(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
168 static void rpn_div_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
170 if (mpfr_sgn(b
->mf
) == 0)
173 mpfr_div(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
176 static void rpn_and_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
178 rpn_exec_int(r
, a
, b
, mpz_and
);
181 static void rpn_or_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
183 rpn_exec_int(r
, a
, b
, mpz_ior
);
186 static void rpn_xor_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
188 rpn_exec_int(r
, a
, b
, mpz_xor
);
191 static void rpn_shl_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
195 mpfr_trunc(r
->mf
, b
->mf
);
196 if (mpfr_fits_ulong_p(r
->mf
, MPFR_DEFAULT_RND
) == 0)
199 e
= mpfr_get_ui(r
->mf
, MPFR_DEFAULT_RND
);
200 mpfr_mul_2exp(r
->mf
, a
->mf
, e
, MPFR_DEFAULT_RND
);
204 static void rpn_shr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
208 mpfr_trunc(r
->mf
, b
->mf
);
209 if (mpfr_fits_ulong_p(r
->mf
, MPFR_DEFAULT_RND
) == 0)
212 e
= mpfr_get_ui(r
->mf
, MPFR_DEFAULT_RND
);
213 mpfr_div_2exp(r
->mf
, a
->mf
, e
, MPFR_DEFAULT_RND
);
217 static void rpn_pow_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
219 mpfr_pow(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
222 static void rpn_sqr_f(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
224 if (mpfr_sgn(b
->mf
) == 0)
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
);
237 /* Integer mode calculations */
238 static void rpn_add_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
240 rpn_exec_int(r
, a
, b
, mpz_add
);
243 static void rpn_sub_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
245 rpn_exec_int(r
, a
, b
, mpz_sub
);
248 static void rpn_mul_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
250 rpn_exec_int(r
, a
, b
, mpz_mul
);
253 static void rpn_div_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
255 if (mpfr_sgn(b
->mf
) == 0)
258 rpn_exec_int(r
, a
, b
, mpz_tdiv_q
);
261 static void rpn_mod_i(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
263 if (mpfr_sgn(b
->mf
) == 0)
266 rpn_exec_int(r
, a
, b
, mpz_tdiv_r
);
269 /* Percent mode calculations */
270 static void rpn_add_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
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
);
282 static void rpn_sub_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
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
);
294 static void rpn_mul_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
296 mpfr_mul(r
->mf
, a
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
297 mpfr_div_ui(r
->mf
, r
->mf
, 100, MPFR_DEFAULT_RND
);
300 static void rpn_div_p(calc_number_t
*r
, calc_number_t
*a
, calc_number_t
*b
)
302 if (mpfr_sgn(b
->mf
) == 0)
305 mpfr_mul_ui(r
->mf
, a
->mf
, 100, MPFR_DEFAULT_RND
);
306 mpfr_div(r
->mf
, r
->mf
, b
->mf
, MPFR_DEFAULT_RND
);
310 void run_operator(calc_node_t
*result
,
313 unsigned int operation
)
315 if (calc
.base
== IDC_RADIO_DEC
) {
317 percent_mode
= FALSE
;
318 operator_list
[operation
].op_p(&result
->number
, &a
->number
, &b
->number
);
320 operator_list
[operation
].op_f(&result
->number
, &a
->number
, &b
->number
);
322 operator_list
[operation
].op_i(&result
->number
, &a
->number
, &b
->number
);
323 /* apply final limiter to result */
324 apply_int_mask(&result
->number
);
328 static void evalStack(calc_number_t
*number
)
333 mpfr_init(ip
.number
.mf
);
336 prec
= operator_list
[ip
.operation
].prec
;
337 while (!is_stack_empty()) {
340 if (prec
<= operator_list
[op
->operation
].prec
) {
341 if (op
->operation
== RPN_OPERATOR_PARENT
) continue;
343 rpn_copy(&calc
.prev
, &ip
.number
);
344 run_operator(&ip
, op
, &ip
, op
->operation
);
347 mpfr_clear(ip
.number
.mf
);
356 if (ip
.operation
!= RPN_OPERATOR_EQUAL
&& ip
.operation
!= RPN_OPERATOR_PERCENT
)
359 calc
.prev_operator
= op
->operation
;
361 rpn_copy(number
, &ip
.number
);
362 mpfr_clear(ip
.number
.mf
);
365 int exec_infix2postfix(calc_number_t
*number
, unsigned int func
)
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 */
377 if (func
== RPN_OPERATOR_PERCENT
)
380 mpfr_init(tmp
.number
.mf
);
381 rpn_copy(&tmp
.number
, number
);
382 tmp
.operation
= func
;
385 mpfr_clear(tmp
.number
.mf
);
387 if (func
== RPN_OPERATOR_NONE
)
390 if (func
!= RPN_OPERATOR_PARENT
) {
391 calc
.last_operator
= func
;
397 void exec_change_infix(void)
399 stack_node_t
*op
= stack
;
403 if (op
->node
.operation
== RPN_OPERATOR_PARENT
||
404 op
->node
.operation
== RPN_OPERATOR_PERCENT
||
405 op
->node
.operation
== RPN_OPERATOR_EQUAL
)
407 /* remove the head, it will be re-inserted with new operator */
411 void exec_closeparent(calc_number_t
*number
)
415 rpn_alloc(&ip
.number
);
416 rpn_copy(&ip
.number
, number
);
417 while (!is_stack_empty()) {
420 if (op
->operation
== RPN_OPERATOR_PARENT
)
423 run_operator(&ip
, op
, &ip
, op
->operation
);
429 rpn_copy(number
, &ip
.number
);
430 rpn_free(&ip
.number
);
433 int eval_parent_count(void)
435 stack_node_t
*s
= stack
;
439 if (s
->node
.operation
== RPN_OPERATOR_PARENT
)
441 s
= (stack_node_t
*)(s
->next
);
446 void flush_postfix(void)
448 while (!is_stack_empty())
450 /* clear prev and last typed operators */
452 calc
.last_operator
= 0;
455 void start_rpn_engine(void)
457 mpf_set_default_prec(512);
458 mpfr_set_default_prec(512);
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
);
464 rpn_zero(&calc
.memory
.number
);
467 void stop_rpn_engine(void)
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
);