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 { 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_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); 53 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); 65 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); 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 { 115 stack_node_t *z = (stack_node_t *)malloc(sizeof(stack_node_t)); 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 */ 132 static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 133 { 134 r->f = a->f + b->f; 135 } 136 137 static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 138 { 139 r->f = a->f - b->f; 140 } 141 142 static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 143 { 144 r->f = a->f * b->f; 145 } 146 147 static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 148 { 149 if (b->f == 0) 150 calc.is_nan = TRUE; 151 else 152 r->f = a->f / b->f; 153 } 154 155 static void rpn_mod_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 167 static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 177 static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 187 static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 197 static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 198 { 199 calc_number_t n; 200 201 modf(b->f, &n.f); 202 203 r->f = a->f * pow(2., n.f); 204 } 205 206 static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 207 { 208 calc_number_t n; 209 210 modf(b->f, &n.f); 211 212 r->f = a->f / pow(2., n.f); 213 } 214 215 static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 222 static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b) 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 */ 234 static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 235 { 236 r->i = a->i + b->i; 237 } 238 239 static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 240 { 241 r->i = a->i - b->i; 242 } 243 244 static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 245 { 246 r->i = a->i * b->i; 247 } 248 249 static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 250 { 251 if (b->i == 0) 252 calc.is_nan = TRUE; 253 else 254 r->i = a->i / b->i; 255 } 256 257 static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 258 { 259 if (b->i == 0) 260 calc.is_nan = TRUE; 261 else 262 r->i = a->i % b->i; 263 } 264 265 static void rpn_and_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 266 { 267 r->i = a->i & b->i; 268 } 269 270 static void rpn_or_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 271 { 272 r->i = a->i | b->i; 273 } 274 275 static void rpn_xor_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 276 { 277 r->i = a->i ^ b->i; 278 } 279 280 static void rpn_shl_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 281 { 282 r->i = a->i << b->i; 283 } 284 285 static void rpn_shr_i(calc_number_t *r, calc_number_t *a, calc_number_t *b) 286 { 287 r->i = a->i >> b->i; 288 } 289 290 /* Percent mode calculations */ 291 static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 292 { 293 r->f = a->f * (1. + b->f/100.); 294 } 295 296 static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 297 { 298 r->f = a->f * (1. - b->f/100.); 299 } 300 301 static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 302 { 303 r->f = a->f * b->f / 100.; 304 } 305 306 static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) 307 { 308 if (b->f == 0) 309 calc.is_nan = TRUE; 310 else 311 r->f = a->f * 100. / b->f; 312 } 313 314 void run_operator(calc_node_t *result, 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); 326 base = IDC_RADIO_DEC; 327 } else 328 if (a->base != IDC_RADIO_DEC && b->base == IDC_RADIO_DEC) { 329 da.f = logic_int2dbl(&a->number); 330 base = IDC_RADIO_DEC; 331 } 332 333 if (base == IDC_RADIO_DEC) { 334 if (percent_mode) { 335 percent_mode = FALSE; 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 357 static void evalStack(calc_number_t *number) 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 391 int exec_infix2postfix(calc_number_t *number, unsigned int func) 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) { 416 calc.last_operator = func; 417 evalStack(number); 418 } 419 return 1; 420 } 421 422 void exec_change_infix(void) 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 436 void exec_closeparent(calc_number_t *number) 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 457 int eval_parent_count(void) 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 */ 475 calc.prev_operator = 476 calc.last_operator = 0; 477 } 478 479 void start_rpn_engine(void) 480 { 481 stack = NULL; 482 } 483 484 void stop_rpn_engine(void) 485 { 486 } 487