/* * Raise num to exp (an integer) */ FUNCTION DOUBLE power ( DOUBLE num, /* input: the number to raise */ FUNINT exp /* input: the exponent */ ) { DOUBLE temp; TAEINT i; temp = 1; if (exp>=0) { for(i=1; i<=exp; i++) if (fl_mult(temp, num, &temp) != SUCCESS) /* floating mult routine */ return(0); /* failure */ return(temp); } else { for (i=1; i <= -exp; i++) if (fl_div(temp, num, &temp) != SUCCESS) return(0); return(temp); } }
static sCmdArg eval_binOpExp(const sASTNode *node,octa offset,bool *finished) { sCmdArg res = {ARGVAL_INT,ORG_EXPR,0,{0}}; sCmdArg left = eval_get(node->d.binOpExp.left,offset,finished); sCmdArg right = eval_get(node->d.binOpExp.right,offset,finished); if(left.type == ARGVAL_STR || right.type == ARGVAL_STR) cmds_throwEx("Unsupported operation!\n"); if(left.type == ARGVAL_FLOAT || right.type == ARGVAL_FLOAT) { unsigned ex; if(left.type != ARGVAL_FLOAT) { left.d.integer = fl_floatit(left.d.integer,0,true,false,&ex); left.type = ARGVAL_FLOAT; } if(right.type != ARGVAL_FLOAT) { right.d.integer = fl_floatit(right.d.integer,0,true,false,&ex); right.type = ARGVAL_FLOAT; } res.type = ARGVAL_FLOAT; switch(node->d.binOpExp.op) { case BINOP_ADD: res.d.integer = fl_add(left.d.integer,right.d.integer,&ex); break; case BINOP_SUB: res.d.integer = fl_sub(left.d.integer,right.d.integer,&ex); break; case BINOP_MULU: case BINOP_MUL: res.d.integer = fl_mult(left.d.integer,right.d.integer,&ex); break; case BINOP_DIVU: case BINOP_DIV: res.d.integer = fl_divide(left.d.integer,right.d.integer,&ex); break; case BINOP_MODU: case BINOP_MOD: // 2500 makes sure that the remainder can be calculated in one step res.d.integer = fl_remstep(left.d.integer,right.d.integer,2500,&ex); break; case BINOP_AND: case BINOP_OR: case BINOP_XOR: case BINOP_SL: case BINOP_SAR: case BINOP_SR: cmds_throwEx("Unsupported operation!\n"); break; default: assert(false); break; } } else { // note: some of the operations are the same on x86 and mmix. but some of them aren't. // therefore, we use the mmix-integer-arithmetic-functions if they are different. octa aux; switch(node->d.binOpExp.op) { case BINOP_ADD: res.d.integer = left.d.integer + right.d.integer; break; case BINOP_SUB: res.d.integer = left.d.integer - right.d.integer; break; case BINOP_MUL: res.d.integer = int_smult(left.d.integer,right.d.integer,&aux); break; case BINOP_MULU: res.d.integer = int_umult(left.d.integer,right.d.integer,&aux); break; case BINOP_DIV: res.d.integer = int_sdiv(left.d.integer,right.d.integer,&aux); break; case BINOP_DIVU: res.d.integer = int_udiv(0,left.d.integer,right.d.integer,&aux); break; case BINOP_MOD: int_sdiv(left.d.integer,right.d.integer,&aux); res.d.integer = aux; break; case BINOP_MODU: int_udiv(0,left.d.integer,right.d.integer,&aux); res.d.integer = aux; break; case BINOP_AND: res.d.integer = left.d.integer & right.d.integer; break; case BINOP_OR: res.d.integer = left.d.integer | right.d.integer; break; case BINOP_XOR: res.d.integer = left.d.integer ^ right.d.integer; break; case BINOP_SL: res.d.integer = int_shiftLeft(left.d.integer,right.d.integer); break; case BINOP_SAR: res.d.integer = int_shiftRightArith(left.d.integer,right.d.integer); break; case BINOP_SR: res.d.integer = int_shiftRightLog(left.d.integer,right.d.integer); break; default: assert(false); break; } } if(offset == 0) *finished = false; return res; }