Mercurial > mm7
changeset 1130:d98415be04ca
banker's rounding template
author | Grumpy7 |
---|---|
date | Fri, 31 May 2013 23:38:43 +0200 |
parents | 9362028fccd1 |
children | 71ba92960bc5 f947bedb2859 |
files | Math.h mm7_2.cpp |
diffstat | 2 files changed, 84 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- 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 <cmath> +#include <cstdlib> +#include <ciso646> + +namespace rounding +{ + + //-------------------------------------------------------------------------- + // round down + // Bias: -Infinity + using std::floor; + + //-------------------------------------------------------------------------- + // round up + // Bias: +Infinity + using std::ceil; + + //-------------------------------------------------------------------------- + // symmetric round up + // Bias: away from zero + template <typename FloatType> + 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 <typename FloatType> + FloatType roundhalfup( const FloatType& value ) + { + return std::floor( value +0.5 ); + } + + //-------------------------------------------------------------------------- + // symmetric round half up + // Bias: away from zero + template <typename FloatType> + 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 <typename FloatType> + FloatType bankersRounding( + const FloatType& value, + const FloatType& epsilon = ROUNDING_EPSILON + ) { + if (value < 0.0) return -bankersRounding <FloatType> ( -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
--- 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;