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 { 24 calc_node_t node; 25 void *next; 26 } stack_node_t; 27 28 typedef void (*operator_call)(calc_number_t *, calc_number_t *, calc_number_t *); 29 30 typedef struct { 31 unsigned int prec; 32 operator_call op_f; 33 operator_call op_i; 34 operator_call op_p; 35 } calc_operator_t; 36 37 static stack_node_t *stack; 38 static calc_node_t temp; 39 static BOOL percent_mode; 40 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); 52 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); 59 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); 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 84 static void node_copy(calc_node_t *dst, calc_node_t *src) 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 { 116 stack_node_t *z = (stack_node_t *)malloc(sizeof(stack_node_t)); 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 */ 153 static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 154 { 155 mpfr_add(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND); 156 } 157 158 static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 159 { 160 mpfr_sub(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND); 161 } 162 163 static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 164 { 165 mpfr_mul(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND); 166 } 167 168 static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 176 static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 177 { 178 rpn_exec_int(r, a, b, mpz_and); 179 } 180 181 static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 182 { 183 rpn_exec_int(r, a, b, mpz_ior); 184 } 185 186 static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 187 { 188 rpn_exec_int(r, a, b, mpz_xor); 189 } 190 191 static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 204 static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 217 static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 218 { 219 mpfr_pow(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND); 220 } 221 222 static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 */ 238 static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 239 { 240 rpn_exec_int(r, a, b, mpz_add); 241 } 242 243 static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 244 { 245 rpn_exec_int(r, a, b, mpz_sub); 246 } 247 248 static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 249 { 250 rpn_exec_int(r, a, b, mpz_mul); 251 } 252 253 static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 261 static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 */ 270 static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 282 static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 294 static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 300 static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 310 void run_operator(calc_node_t *result, 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) { 317 percent_mode = FALSE; 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 328 static void evalStack(calc_number_t *number) 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 365 int exec_infix2postfix(calc_number_t *number, unsigned int func) 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) { 391 calc.last_operator = func; 392 evalStack(number); 393 } 394 return 1; 395 } 396 397 void exec_change_infix(void) 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 411 void exec_closeparent(calc_number_t *number) 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 433 int eval_parent_count(void) 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 */ 451 calc.prev_operator = 452 calc.last_operator = 0; 453 } 454 455 void start_rpn_engine(void) 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); 464 rpn_zero(&calc.memory.number); 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 } 474