diff -r a93b96b49985 -r e9182dc00c6d Fraction.st --- a/Fraction.st Fri Feb 26 06:41:16 2016 +0100 +++ b/Fraction.st Sat Feb 27 12:59:25 2016 +0000 @@ -1,3 +1,5 @@ +"{ Encoding: utf8 }" + " COPYRIGHT (c) 1989 by Claus Gittinger All Rights Reserved @@ -88,56 +90,76 @@ %{ /* NOCONTEXT */ #ifdef __SCHTEAM__ if (self == Fraction.Class) { - return context._RETURN(new STFraction(num, den)); + return context._RETURN(new STFraction(num, den)); } #else /* this check allows subclassing .. */ if (self == Fraction) { - if (__bothSmallInteger(num, den)) { - if (den != __mkSmallInteger(0)) { - if (__CanDoQuickAlignedNew(sizeof(struct __Fraction))) { /* OBJECT ALLOCATION */ - OBJ newFraction; - int spc; - INT iDen; + if (__bothSmallInteger(num, den)) { + if (den != __mkSmallInteger(0)) { + if (__CanDoQuickAlignedNew(sizeof(struct __Fraction))) { /* OBJECT ALLOCATION */ + OBJ newFraction; + INT iDen; + INT iNum; + + __qCheckedAlignedNew(newFraction, sizeof(struct __Fraction)); + __InstPtr(newFraction)->o_class = self; + __qSTORE(newFraction, self); + + iDen = __intVal(den); + iNum = __intVal(num); - __qCheckedAlignedNew(newFraction, sizeof(struct __Fraction)); - __InstPtr(newFraction)->o_class = self; - __qSTORE(newFraction, self); - iDen = __intVal(den); - if (iDen != 0) { - if (iDen < 0) { - __FractionInstPtr(newFraction)->f_numerator = __mkSmallInteger(- __intVal(num)); - __FractionInstPtr(newFraction)->f_denominator = __mkSmallInteger(- iDen); - } else { - __FractionInstPtr(newFraction)->f_numerator = num; - __FractionInstPtr(newFraction)->f_denominator = den; - } - if (num == __mkSmallInteger(1)) { - /* no need to reduce */ - RETURN ( newFraction ); - } - } - } - } - } + if (iDen < 0) { + iNum = -iNum; + iDen = -iDen; + } + while ( (((iNum | iDen) & 1) == 0) && ( iNum != 0) && ( iDen != 0)) { + /* both even and non-zero */ + iNum = iNum >> 1; + iDen = iDen >> 1; + } + if (iNum >= _MAX_INT) { + __FractionInstPtr(newFraction)->f_numerator = __MKINT(iNum); + } else { + __FractionInstPtr(newFraction)->f_numerator = __MKSMALLINT(iNum); + } + if (iDen >= _MAX_INT) { + __FractionInstPtr(newFraction)->f_denominator = __MKINT(iDen); + } else { + __FractionInstPtr(newFraction)->f_denominator = __MKSMALLINT(iDen); + } + if (iNum == 1) { + /* no need to reduce */ + RETURN ( newFraction ); + } + } + } + } } #endif /* not __SCHTEAM__ */ %}. den = 0 ifTrue:[ - ^ ZeroDivide raiseRequestWith:thisContext. + ^ ZeroDivide raiseRequestWith:thisContext. ]. newFraction isNil ifTrue:[ - newFraction := self basicNew setNumerator:num denominator:den. + newFraction := self basicNew setNumerator:num denominator:den. ]. ^ newFraction reduced " - Fraction numerator:1 denominator:3 - Fraction numerator:2 denominator:6 + Fraction numerator:1 denominator:3 + Fraction numerator:2 denominator:3 + Fraction numerator:2 denominator:6 + + Fraction numerator:1 denominator:0 -> error + Fraction numerator:2 denominator:0 -> error - Fraction numerator:1 denominator:0 - Fraction numerator:2 denominator:0 + Fraction numerator:5 denominator:10 + Fraction numerator:50 denominator:100 + Fraction numerator:8 denominator:16 " + + "Modified: / 27-02-2016 / 00:25:47 / cg" ! readDecimalFractionFrom:aStringOrStream onError:exceptionBlock