diff -r 34ed3b6c7307 -r 219a5a47e8b1 SmallInteger.st --- a/SmallInteger.st Sat Aug 13 06:52:18 2016 +0200 +++ b/SmallInteger.st Tue Aug 23 09:54:28 2016 +0100 @@ -621,12 +621,12 @@ The result is truncated toward negative infinity and will be negative, if the operands signs differ. The following is always true: - (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver + (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. Especially surprising: - -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1. - -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4. + -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1. + -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4. See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder." @@ -648,95 +648,95 @@ INT dividend = __intVal(self); if (__isSmallInteger(aNumber)) { - divisor = __intVal(aNumber); - if (divisor != 0) { - rslt = dividend / divisor; - /* - * Optimized to speed up positive result - */ - if (rslt <= 0) { - if (rslt == 0) { - if ((dividend ^ divisor) < 0) { - /* - * result (negative) has been truncated toward 0. - * Return -1, because we truncate toward negative inf. - */ - rslt = -1; - } - } else { - /* - * If result (negative) has been truncated toward 0, - * subtract 1, because we truncate toward negative inf. - */ - if (divisor > 0) { - if (rslt * divisor > dividend) { - rslt--; - } - } else { - if (rslt * divisor < dividend) { - rslt--; - } - } - } - } - RETURN ( __mkSmallInteger(rslt) ); - } + divisor = __intVal(aNumber); + if (divisor != 0) { + rslt = dividend / divisor; + /* + * Optimized to speed up positive result + */ + if (rslt <= 0) { + if (rslt == 0) { + if ((dividend ^ divisor) < 0) { + /* + * result (negative) has been truncated toward 0. + * Return -1, because we truncate toward negative inf. + */ + rslt = -1; + } + } else { + /* + * If result (negative) has been truncated toward 0, + * subtract 1, because we truncate toward negative inf. + */ + if (divisor > 0) { + if (rslt * divisor > dividend) { + rslt--; + } + } else { + if (rslt * divisor < dividend) { + rslt--; + } + } + } + } + RETURN ( __mkSmallInteger(rslt) ); + } } else { - if (__isFractionLike(aNumber)) { - OBJ t = __FractionInstPtr(aNumber)->f_numerator; - if (__isSmallInteger(t)) { - INT num = __intVal(t); - t = __FractionInstPtr(aNumber)->f_denominator; - if (__isSmallInteger(t)) { - INT den = __intVal(t); - INT prod; + if (__isFractionLike(aNumber)) { + OBJ t = __FractionInstPtr(aNumber)->f_numerator; + if (__isSmallInteger(t)) { + INT num = __intVal(t); + t = __FractionInstPtr(aNumber)->f_denominator; + if (__isSmallInteger(t)) { + INT den = __intVal(t); + INT prod; #if 0 && defined(__GNUC__) // supported from GCC 5 - if (!__builtin_mul_overflow(myself, den, &prod)) { - goto out; // overflow, try harder... - } + if (!__builtin_mul_overflow(myself, den, &prod)) { + goto out; // overflow, try harder... + } #else - prod = dividend * den; - // make sure, that no overflow occured - if (prod / den != dividend) { - goto out; // overflow, try harder... - } + prod = dividend * den; + // make sure, that no overflow occurred + if (prod / den != dividend) { + goto out; // overflow, try harder... + } #endif - rslt = prod / num; - - /* - * Optimized to speed up positive result - */ - if (rslt <= 0) { - if (rslt == 0) { - if ((dividend ^ num) < 0) { - /* - * result (negative) has been truncated toward 0. - * Return -1, because we truncate toward negative inf. - */ - rslt = -1; - } - } else { - /* - * If result (negative) has been truncated toward 0, - * subtract 1, because we truncate toward negative inf. - */ - if (num > 0) { - if (rslt * num > prod) rslt--; - } else { - if (rslt * num < prod) rslt--; - } - } - } - RETURN ( __mkSmallInteger(rslt) ); - } - } - } + rslt = prod / num; + + /* + * Optimized to speed up positive result + */ + if (rslt <= 0) { + if (rslt == 0) { + if ((dividend ^ num) < 0) { + /* + * result (negative) has been truncated toward 0. + * Return -1, because we truncate toward negative inf. + */ + rslt = -1; + } + } else { + /* + * If result (negative) has been truncated toward 0, + * subtract 1, because we truncate toward negative inf. + */ + if (num > 0) { + if (rslt * num > prod) rslt--; + } else { + if (rslt * num < prod) rslt--; + } + } + } + RETURN ( __mkSmallInteger(rslt) ); + } + } + } } out:; #endif /* not __SCHTEAM__ */ %}. (aNumber = 0) ifTrue:[ - ^ ZeroDivide raiseRequestWith:thisContext. + ^ ZeroDivide raiseRequestWith:thisContext. ]. ^ aNumber integerQuotientFromInteger:self @@ -900,7 +900,7 @@ and the argument's value. The result is truncated towards zero and negative, if the operands signs differ.. The following is always true: - (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver + (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver For positive results, this is the same as #//, for negative results, the remainder is ignored. I.e.: '9 // 4 = 2' and '-9 // 4 = -3' @@ -911,39 +911,39 @@ return context._RETURN( self.quotient(aNumber)); #else if (__isSmallInteger(aNumber)) { - INT val = __intVal(aNumber); - if (val != 0) { - RETURN ( __mkSmallInteger(__intVal(self) / val) ); - } + INT val = __intVal(aNumber); + if (val != 0) { + RETURN ( __mkSmallInteger(__intVal(self) / val) ); + } } else { - if (__isFractionLike(aNumber)) { - OBJ t = __FractionInstPtr(aNumber)->f_numerator; - if (__isSmallInteger(t)) { - INT num = __intVal(t); - t = __FractionInstPtr(aNumber)->f_denominator; - if (__isSmallInteger(t)) { - INT den = __intVal(t); - INT myself = __intVal(self); - INT prod; + if (__isFractionLike(aNumber)) { + OBJ t = __FractionInstPtr(aNumber)->f_numerator; + if (__isSmallInteger(t)) { + INT num = __intVal(t); + t = __FractionInstPtr(aNumber)->f_denominator; + if (__isSmallInteger(t)) { + INT den = __intVal(t); + INT myself = __intVal(self); + INT prod; #if 0 && defined(__GNUC__) // supported from GCC 5 - if (__builtin_mul_overflow(myself, den, &prod)) { - RETURN ( __mkSmallInteger(prod / num )); - } + if (__builtin_mul_overflow(myself, den, &prod)) { + RETURN ( __mkSmallInteger(prod / num )); + } #else - prod = myself * den; - // make sure, that no overflow occured - if (prod / den == myself) { - RETURN ( __mkSmallInteger(prod / num )); - } + prod = myself * den; + // make sure, that no overflow occurred + if (prod / den == myself) { + RETURN ( __mkSmallInteger(prod / num )); + } #endif - } - } - } + } + } + } } #endif /* not __SCHTEAM__ */ %}. (aNumber = 0) ifTrue:[ - ^ ZeroDivide raiseRequestWith:thisContext. + ^ ZeroDivide raiseRequestWith:thisContext. ]. ^ self retry:#quo: coercing:aNumber