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;