diff --git a/extra/math/extras/extras-tests.factor b/extra/math/extras/extras-tests.factor index 6a93f2809e..4219c1df1f 100644 --- a/extra/math/extras/extras-tests.factor +++ b/extra/math/extras/extras-tests.factor @@ -89,3 +89,17 @@ IN: math.extras.test [ 2 ] [ { 1 1 2 2 2 } majority ] unit-test [ 3 ] [ { 1 2 3 1 2 3 1 2 3 3 } majority ] unit-test { CHAR: C } [ "AAACCBBCCCBCC" majority ] unit-test + +[ -5 ] [ -4-3/5 round-to-even ] unit-test +[ -4 ] [ -4-1/2 round-to-even ] unit-test +[ -4 ] [ -4-2/5 round-to-even ] unit-test +[ 5 ] [ 4+3/5 round-to-even ] unit-test +[ 4 ] [ 4+1/2 round-to-even ] unit-test +[ 4 ] [ 4+2/5 round-to-even ] unit-test + +[ -5.0 ] [ -4.6 round-to-even ] unit-test +[ -4.0 ] [ -4.5 round-to-even ] unit-test +[ -4.0 ] [ -4.4 round-to-even ] unit-test +[ 5.0 ] [ 4.6 round-to-even ] unit-test +[ 4.0 ] [ 4.5 round-to-even ] unit-test +[ 4.0 ] [ 4.4 round-to-even ] unit-test diff --git a/extra/math/extras/extras.factor b/extra/math/extras/extras.factor index 41fc59949c..b2b7fc313e 100644 --- a/extra/math/extras/extras.factor +++ b/extra/math/extras/extras.factor @@ -238,3 +238,17 @@ PRIVATE> : compression-dissimilarity ( a b -- n ) compression-lengths + / ; + +GENERIC: round-to-even ( x -- y ) + +M: integer round-to-even ; inline + +M: ratio round-to-even + >fraction [ /mod abs 2 * ] keep > [ dup 0 < -1 1 ? + ] when ; + +M: float round-to-even + dup 0 > [ + dup 0x1p52 <= [ 0x1p52 + 0x1p52 - ] when + ] [ + dup -0x1p52 >= [ 0x1p52 - 0x1p52 + ] when + ] if ;