extern "C" Box* pow_i64_i64(i64 lhs, i64 rhs) { i64 orig_rhs = rhs; i64 rtn = 1, curpow = lhs; if (rhs < 0) return boxFloat(pow_float_float(lhs, rhs)); if (rhs == 0) { if (lhs < 0) return boxInt(-1); return boxInt(1); } assert(rhs > 0); while (rhs) { if (rhs & 1) { // TODO: could potentially avoid restarting the entire computation on overflow? if (__builtin_smull_overflow(rtn, curpow, &rtn)) return longPow(boxLong(lhs), boxLong(orig_rhs)); } if (__builtin_smull_overflow(curpow, curpow, &curpow)) return longPow(boxLong(lhs), boxLong(orig_rhs)); rhs >>= 1; } return boxInt(rtn); }
OBJ readNumber(OBJ inStream, char firstChar, int isNegative){ //printf(YEL "\nreadNumber>" RESET); /* * TO-DO refactor! */ jscheme_int64 *iVal = NULL; char ch; OBJ retVal; // substract the ASCII value of '0' from char to get the actual value between 0 and 9. jscheme_int64 start = (jscheme_int64) firstChar - '0'; if(isNegative) start *= -1; iVal = &start; while( isDigit( ch = nextChar(inStream) )){ //iVal = iVal * 10 + ( (int)ch - '0'); jscheme_int64 ch_val = (jscheme_int64) ch - '0'; if(isNegative){ int mul = __builtin_smull_overflow(*iVal, 10, iVal); int sub = __builtin_ssubl_overflow(*iVal, ch_val, iVal); if( mul || sub ){ if(thisIsTheEnd(inStream)){ prompt_on(); } js_error("readNumber: integer underflow", newInteger(*iVal)); } }else{ int mul = __builtin_smull_overflow(*iVal, 10, iVal); int add = __builtin_saddl_overflow(*iVal, ch_val, iVal); if( mul || add ){ if(thisIsTheEnd(inStream)){ prompt_on(); } js_error("readNumber: integer overflow", newInteger(*iVal)); } } } unreadChar(inStream, ch); retVal = newInteger( *iVal ); return retVal; }
OBJ builtin_times(int numArgs){ jscheme_int64 *product= NULL; jscheme_int64 start = 1; product = &start; for(int i = 0; i < numArgs; i++){ OBJ theArg = POP(); if( !ISINTEGER(theArg)){ POPN((numArgs - 1) - i); js_error("(*): non-integer argument", theArg); } if(__builtin_smull_overflow(*product,INTVAL(theArg),product)){ // clean stack POPN((numArgs - 1) - i); js_error("(*): integer overflow", newInteger(*product)); } } return newInteger(*product); }
extern "C" Box* mul_i64_i64(i64 lhs, i64 rhs) { i64 result; if (!__builtin_smull_overflow(lhs, rhs, &result)) return boxInt(result); return longMul(boxLong(lhs), boxLong(rhs)); }