# HG changeset patch # User Grumpy7 # Date 1370036323 -7200 # Node ID d98415be04ca13ea517b49cc2356c98e1105458d # Parent 9362028fccd191ed1d3da4280158d7328f018b02 banker's rounding template diff -r 9362028fccd1 -r d98415be04ca Math.h --- a/Math.h Fri May 31 06:36:34 2013 +0200 +++ b/Math.h Fri May 31 23:38:43 2013 +0200 @@ -29,5 +29,84 @@ int fixpoint_mul(int, int); int fixpoint_from_float(float value); +#ifndef ROUNDING_EPSILON +#define ROUNDING_EPSILON 0.0000001 +#endif +#include +#include +#include + +namespace rounding +{ + + //-------------------------------------------------------------------------- + // round down + // Bias: -Infinity + using std::floor; + + //-------------------------------------------------------------------------- + // round up + // Bias: +Infinity + using std::ceil; + + //-------------------------------------------------------------------------- + // symmetric round up + // Bias: away from zero + template + FloatType ceil0( const FloatType& value ) + { + FloatType result = std::ceil( std::fabs( value ) ); + return (value < 0.0) ? -result : result; + } + + //-------------------------------------------------------------------------- + // Common rounding: round half up + // Bias: +Infinity + template + FloatType roundhalfup( const FloatType& value ) + { + return std::floor( value +0.5 ); + } + + //-------------------------------------------------------------------------- + // symmetric round half up + // Bias: away from zero + template + FloatType roundhalfup0( const FloatType& value ) + { + FloatType result = roundhalfup( std::fabs( value ) ); + return (value < 0.0) ? -result : result; + } + + //-------------------------------------------------------------------------- + // round half even (banker's rounding) + // Bias: none + template + FloatType bankersRounding( + const FloatType& value, + const FloatType& epsilon = ROUNDING_EPSILON + ) { + if (value < 0.0) return -bankersRounding ( -value, epsilon ); + + FloatType ipart; + std::modf( value, &ipart ); + + // If 'value' is exctly halfway between two integers + if (abs((value -(ipart +0.5))) < epsilon) + { + // If 'ipart' is even then return 'ipart' + if (std::fmod( ipart, 2.0 ) < epsilon) + return ipart; + + // Else return the nearest even integer + return ceil0( ipart +0.5 ); + } + + // Otherwise use the usual round to closest + // (Either symmetric half-up or half-down will do0 + return roundhalfup0( value ); + } + +} extern struct stru193_math *stru_5C6E00; \ No newline at end of file diff -r 9362028fccd1 -r d98415be04ca mm7_2.cpp --- a/mm7_2.cpp Fri May 31 06:36:34 2013 +0200 +++ b/mm7_2.cpp Fri May 31 23:38:43 2013 +0200 @@ -2237,6 +2237,7 @@ unsigned int a6r; // [sp+A0h] [bp+18h]@218 int dstdiffmult; + using namespace rounding; int probablyBitDepth = this->field_20.field_C; switch(probablyBitDepth) @@ -2276,13 +2277,13 @@ while ( 1 ) { a6s = (double)v14 / (double)dstWidth * (double)srcWidth; - v151 = floorf(a6s + 0.5f);//a6s + 6.7553994e15; + v151 = bankersRounding(a6s);//a6s + 6.7553994e15; a6t = (double)(v14 + 1) / (double)dstWidth * (double)srcWidth; - v142 = floorf(a6t + 0.5f);//a6t + 6.7553994e15; + v142 = bankersRounding(a6t);//a6t + 6.7553994e15; v17 = (double)v231 / (double)dstHeight * (double)srcHeight; - v133 = floorf(v17 + 0.5f);//v17 + 6.7553994e15; + v133 = bankersRounding(v17);//v17 + 6.7553994e15; v18 = (double)(v231 + 1) / (double)dstHeight * (double)srcHeight; - v124 = floorf(v18 + 0.5f);//v18 + 6.7553994e15; + v124 = bankersRounding(v18);//v18 + 6.7553994e15; v19 = (LODWORD(v124) - LODWORD(v133)) * (LODWORD(v142) - LODWORD(v151)); v252 = 0; a6b = 0;