Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rpn_mpfr.c

Go to the documentation of this file.
00001 #include "calc.h"
00002 
00003 typedef struct {
00004     calc_node_t     node;
00005     void           *next;
00006 } stack_node_t;
00007 
00008 typedef void (*operator_call)(calc_number_t *, calc_number_t *, calc_number_t *);
00009 
00010 typedef struct {
00011     unsigned int prec;
00012     operator_call op_f;
00013     operator_call op_i;
00014     operator_call op_p;
00015 } calc_operator_t;
00016 
00017 static stack_node_t *stack;
00018 static stack_node_t  temp;
00019 static BOOL          percent_mode;
00020 
00021 static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00022 static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00023 static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00024 static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00025 static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00026 static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00027 static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00028 static void rpn_or_f (calc_number_t *r, calc_number_t *a, calc_number_t *b);
00029 static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00030 static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00031 static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00032 
00033 /* Integer mode calculations */
00034 static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00035 static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00036 static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00037 static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00038 static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00039 
00040 /* Percentage mode calculations */
00041 static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00042 static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00043 static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00044 static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b);
00045 
00046 static const calc_operator_t operator_list[] = {
00047     { 0, NULL,      NULL,      NULL,      }, // RPN_OPERATOR_PARENT
00048     { 0, NULL,      NULL,      NULL,      }, // RPN_OPERATOR_PERCENT
00049     { 0, NULL,      NULL,      NULL,      }, // RPN_OPERATOR_EQUAL
00050     { 1, rpn_or_f,  rpn_or_f,  NULL,      }, // RPN_OPERATOR_OR
00051     { 2, rpn_xor_f, rpn_xor_f, NULL,      }, // RPN_OPERATOR_XOR
00052     { 3, rpn_and_f, rpn_and_f, NULL,      }, // RPN_OPERATOR_AND
00053     { 4, rpn_shl_f, rpn_shl_f, NULL,      }, // RPN_OPERATOR_LSH
00054     { 4, rpn_shr_f, rpn_shr_f, NULL,      }, // RPN_OPERATOR_RSH
00055     { 5, rpn_add_f, rpn_add_i, rpn_add_p, }, // RPN_OPERATOR_ADD
00056     { 5, rpn_sub_f, rpn_sub_i, rpn_sub_p, }, // RPN_OPERATOR_SUB
00057     { 6, rpn_mul_f, rpn_mul_i, rpn_mul_p, }, // RPN_OPERATOR_MULT
00058     { 6, rpn_div_f, rpn_div_i, rpn_div_p, }, // RPN_OPERATOR_DIV
00059     { 6, rpn_mod_i, rpn_mod_i, NULL,      }, // RPN_OPERATOR_MOD
00060     { 7, rpn_pow_f, NULL,      NULL,      }, // RPN_OPERATOR_POW
00061     { 7, rpn_sqr_f, NULL,      NULL,      }, // RPN_OPERATOR_SQR
00062 };
00063 
00064 static void node_copy(stack_node_t *dst, stack_node_t *src)
00065 {
00066     mpfr_set(dst->node.number.mf,src->node.number.mf,MPFR_DEFAULT_RND);
00067     dst->node.operation = src->node.operation;
00068     dst->next = src->next;
00069 }
00070 
00071 static stack_node_t *pop()
00072 {
00073     if (stack == NULL)
00074         return NULL;
00075 
00076     /* copy the node */
00077     node_copy(&temp, stack);
00078 
00079     /* free the node */
00080     mpfr_clear(stack->node.number.mf);
00081     free(stack);
00082     stack = temp.next;
00083 
00084     return &temp;
00085 }
00086 
00087 static int is_stack_empty(void)
00088 {
00089     return (stack == NULL);
00090 }
00091 
00092 static void push(stack_node_t *op)
00093 {
00094     stack_node_t *z = (stack_node_t *)malloc(sizeof(stack_node_t));
00095 
00096     mpfr_init_set(z->node.number.mf,op->node.number.mf,MPFR_DEFAULT_RND);
00097     z->node.operation = op->node.operation;
00098     z->next = stack;
00099     stack = z;
00100 }
00101 /*
00102 static unsigned int get_prec(unsigned int opc)
00103 {
00104     unsigned int x;
00105 
00106     for (x=0; x<SIZEOF(operator_list); x++)
00107         if (operator_list[x].opc == opc) break;
00108     return operator_list[x].prec;
00109 }
00110 */
00111 
00112 typedef
00113 __GMP_DECLSPEC void (*exec_call_t)
00114 __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
00115 
00116 static void rpn_exec_int(calc_number_t *r, calc_number_t *a, calc_number_t *b, exec_call_t cb)
00117 {
00118     mpz_t ai, bi;
00119 
00120     mpz_init(ai);
00121     mpz_init(bi);
00122     mpfr_get_z(ai, a->mf, MPFR_DEFAULT_RND);
00123     mpfr_get_z(bi, b->mf, MPFR_DEFAULT_RND);
00124     cb(ai, ai, bi);
00125     mpfr_set_z(r->mf, ai, MPFR_DEFAULT_RND);
00126     mpz_clear(ai);
00127     mpz_clear(bi);
00128 }
00129 
00130 
00131 /* Real mode calculations */
00132 static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00133 {
00134     mpfr_add(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00135 }
00136 
00137 static void rpn_sub_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00138 {
00139     mpfr_sub(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00140 }
00141 
00142 static void rpn_mul_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00143 {
00144     mpfr_mul(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00145 }
00146 
00147 static void rpn_div_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00148 {
00149     if (mpfr_sgn(b->mf) == 0)
00150         calc.is_nan = TRUE;
00151     else
00152         mpfr_div(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00153 }
00154 
00155 static void rpn_and_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00156 {
00157     rpn_exec_int(r, a, b, mpz_and);
00158 }
00159 
00160 static void rpn_or_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00161 {
00162     rpn_exec_int(r, a, b, mpz_ior);
00163 }
00164 
00165 static void rpn_xor_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00166 {
00167     rpn_exec_int(r, a, b, mpz_xor);
00168 }
00169 
00170 static void rpn_shl_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00171 {
00172     unsigned long e;
00173 
00174     mpfr_trunc(r->mf, b->mf);
00175     if (mpfr_fits_ulong_p(r->mf, MPFR_DEFAULT_RND) == 0)
00176         calc.is_nan = TRUE;
00177     else {
00178         e = mpfr_get_ui(r->mf, MPFR_DEFAULT_RND);
00179         mpfr_mul_2exp(r->mf, a->mf, e, MPFR_DEFAULT_RND);
00180     }
00181 }
00182 
00183 static void rpn_shr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00184 {
00185     unsigned long e;
00186 
00187     mpfr_trunc(r->mf, b->mf);
00188     if (mpfr_fits_ulong_p(r->mf, MPFR_DEFAULT_RND) == 0)
00189         calc.is_nan = TRUE;
00190     else {
00191         e = mpfr_get_ui(r->mf, MPFR_DEFAULT_RND);
00192         mpfr_div_2exp(r->mf, a->mf, e, MPFR_DEFAULT_RND);
00193     }
00194 }
00195 
00196 static void rpn_pow_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00197 {
00198     mpfr_pow(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00199 }
00200 
00201 static void rpn_sqr_f(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00202 {
00203     if (mpfr_sgn(b->mf) == 0)
00204         calc.is_nan = TRUE;
00205     else {
00206         mpfr_t tmp;
00207 
00208         mpfr_init(tmp);
00209         mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
00210         mpfr_ui_div(tmp, 1, tmp, MPFR_DEFAULT_RND);
00211         mpfr_pow(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
00212         mpfr_clear(tmp);
00213     }
00214 }
00215 
00216 /* Integer mode calculations */
00217 static void rpn_add_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00218 {
00219     rpn_exec_int(r, a, b, mpz_add);
00220 }
00221 
00222 static void rpn_sub_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00223 {
00224     rpn_exec_int(r, a, b, mpz_sub);
00225 }
00226 
00227 static void rpn_mul_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00228 {
00229     rpn_exec_int(r, a, b, mpz_mul);
00230 }
00231 
00232 static void rpn_div_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00233 {
00234     if (mpfr_sgn(b->mf) == 0)
00235         calc.is_nan = TRUE;
00236     else
00237         rpn_exec_int(r, a, b, mpz_tdiv_q);
00238 }
00239 
00240 static void rpn_mod_i(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00241 {
00242     if (mpfr_sgn(b->mf) == 0)
00243         calc.is_nan = TRUE;
00244     else
00245         rpn_exec_int(r, a, b, mpz_tdiv_r);
00246 }
00247 
00248 /* Percent mode calculations */
00249 static void rpn_add_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00250 {
00251     mpfr_t tmp;
00252 
00253     mpfr_init(tmp);
00254     mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
00255     mpfr_div_ui(tmp, tmp, 100, MPFR_DEFAULT_RND);
00256     mpfr_add_ui(tmp, tmp, 1, MPFR_DEFAULT_RND);
00257     mpfr_mul(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
00258     mpfr_clear(tmp);
00259 }
00260 
00261 static void rpn_sub_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00262 {
00263     mpfr_t tmp;
00264 
00265     mpfr_init(tmp);
00266     mpfr_set(tmp, b->mf, MPFR_DEFAULT_RND);
00267     mpfr_div_ui(tmp, tmp, 100, MPFR_DEFAULT_RND);
00268     mpfr_sub_ui(tmp, tmp, 1, MPFR_DEFAULT_RND);
00269     mpfr_mul(r->mf, a->mf, tmp, MPFR_DEFAULT_RND);
00270     mpfr_clear(tmp);
00271 }
00272 
00273 static void rpn_mul_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00274 {
00275     mpfr_mul(r->mf, a->mf, b->mf, MPFR_DEFAULT_RND);
00276     mpfr_div_ui(r->mf, r->mf, 100, MPFR_DEFAULT_RND);
00277 }
00278 
00279 static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b)
00280 {
00281     if (mpfr_sgn(b->mf) == 0)
00282         calc.is_nan = TRUE;
00283     else {
00284         mpfr_mul_ui(r->mf, a->mf, 100, MPFR_DEFAULT_RND);
00285         mpfr_div(r->mf, r->mf, b->mf, MPFR_DEFAULT_RND);
00286     }
00287 }
00288 
00289 
00290 void run_operator(calc_node_t *result,
00291                   calc_node_t *a,
00292                   calc_node_t *b,
00293                   unsigned int operation)
00294 {
00295     if (calc.base == IDC_RADIO_DEC) {
00296         if (percent_mode) {
00297             percent_mode = FALSE;
00298             operator_list[operation].op_p(&result->number, &a->number, &b->number);
00299         } else
00300             operator_list[operation].op_f(&result->number, &a->number, &b->number);
00301     } else {
00302         operator_list[operation].op_i(&result->number, &a->number, &b->number);
00303         /* apply final limitator to result */
00304         apply_int_mask(&result->number);
00305     }
00306 }
00307 
00308 static void evalStack(calc_number_t *number)
00309 {
00310     stack_node_t *op, ip;
00311     unsigned int prec;
00312 
00313     mpfr_init(ip.node.number.mf);
00314     op = pop();
00315     node_copy(&ip, op);
00316     prec = operator_list[ip.node.operation].prec;
00317     while (!is_stack_empty()) {
00318         op = pop();
00319 
00320         if (prec <= operator_list[op->node.operation].prec) {
00321             if (op->node.operation == RPN_OPERATOR_PARENT) continue;
00322 
00323             rpn_copy(&calc.prev, &ip.node.number);
00324             run_operator(&ip.node, &op->node, &ip.node, op->node.operation);
00325             if (calc.is_nan) {
00326                 flush_postfix();
00327                 mpfr_clear(ip.node.number.mf);
00328                 return;
00329             }
00330         } else {
00331             push(op);
00332             break;
00333         }  
00334     }
00335 
00336     if(ip.node.operation != RPN_OPERATOR_EQUAL && ip.node.operation != RPN_OPERATOR_PERCENT)
00337         push(&ip);
00338 
00339     calc.prev_operator = op->node.operation;
00340 
00341     rpn_copy(number, &ip.node.number);
00342     mpfr_clear(ip.node.number.mf);
00343 }
00344 
00345 int exec_infix2postfix(calc_number_t *number, unsigned int func)
00346 {
00347     stack_node_t tmp;
00348 
00349     if (is_stack_empty() && func == RPN_OPERATOR_EQUAL) {
00350         /* if a number has been entered with exponential */
00351         /* notation, I may update it with normal mode */
00352         if (calc.sci_in)
00353             return 1;
00354         return 0;
00355     }
00356 
00357     if (func == RPN_OPERATOR_PERCENT)
00358         percent_mode = TRUE;
00359 
00360     mpfr_init(tmp.node.number.mf);
00361     rpn_copy(&tmp.node.number, number);
00362     tmp.node.operation = func;
00363 
00364     push(&tmp);
00365     mpfr_clear(tmp.node.number.mf);
00366 
00367     if (func == RPN_OPERATOR_NONE)
00368         return 0;
00369 
00370     if (func != RPN_OPERATOR_PARENT) {
00371         calc.last_operator = func;
00372         evalStack(number);
00373     }
00374     return 1;
00375 }
00376 
00377 void exec_change_infix(void)
00378 {
00379     stack_node_t *op = stack;
00380 
00381     if (op == NULL)
00382         return;
00383     if (op->node.operation == RPN_OPERATOR_PARENT ||
00384         op->node.operation == RPN_OPERATOR_PERCENT ||
00385         op->node.operation == RPN_OPERATOR_EQUAL)
00386         return;
00387     /* remove the head, it will be re-inserted with new operator */
00388     pop();
00389 }
00390 
00391 void exec_closeparent(calc_number_t *number)
00392 {
00393     stack_node_t *op, ip;
00394 
00395     rpn_alloc(&ip.node.number);
00396     rpn_copy(&ip.node.number, number);
00397     while (!is_stack_empty()) {
00398         op = pop();
00399 
00400         if (op->node.operation == RPN_OPERATOR_PARENT)
00401             break;
00402 
00403         run_operator(&ip.node, &op->node, &ip.node, op->node.operation);
00404         if (calc.is_nan) {
00405             flush_postfix();
00406             return;
00407         }
00408     }
00409     rpn_copy(number, &ip.node.number);
00410     rpn_free(&ip.node.number);
00411 }
00412 
00413 int eval_parent_count(void)
00414 {
00415     stack_node_t *s = stack;
00416     int           n = 0;
00417 
00418     while (s != NULL) {
00419         if (s->node.operation == RPN_OPERATOR_PARENT)
00420             n++;
00421         s = (stack_node_t *)(s->next);
00422     }
00423     return n;
00424 }
00425 
00426 void flush_postfix()
00427 {
00428     while (!is_stack_empty())
00429         pop();
00430     /* clear prev and last typed operators */
00431     calc.prev_operator = 
00432     calc.last_operator = 0;
00433 }
00434 
00435 void start_rpn_engine(void)
00436 {
00437     mpf_set_default_prec(512);
00438     mpfr_set_default_prec(512);
00439     stack = NULL;
00440     mpfr_init(calc.code.mf);
00441     mpfr_init(calc.prev.mf);
00442     mpfr_init(calc.memory.number.mf);
00443     mpfr_init(temp.node.number.mf);
00444     rpn_zero(&calc.memory.number);
00445 }
00446 
00447 void stop_rpn_engine(void)
00448 {
00449     mpfr_clear(calc.code.mf);
00450     mpfr_clear(calc.prev.mf);
00451     mpfr_clear(calc.memory.number.mf);
00452     mpfr_clear(temp.node.number.mf);
00453 }

Generated on Thu Feb 9 04:38:58 2012 for ReactOS by doxygen 1.6.3

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.