From f09326a1a6d09cee2e6c60034acd86af4c94c06f Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Wed, 20 Aug 2014 00:08:38 -0400 Subject: [PATCH] [base] Use unsigned calculation in `FT_MulDiv'. * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range. --- ChangeLog | 6 ++++++ src/base/ftcalc.c | 35 ++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f25f1e93..cff13e36a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-08-19 Alexei Podtelezhnikov + + [base] Use unsigned calculation in `FT_MulDiv'. + + * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range. + 2014-08-18 Alexei Podtelezhnikov [base] Remove truncation in `FT_DivFix'. diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index 27e9e07b8..9c72a76f4 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -358,11 +358,9 @@ } - /* documentation is in freetype.h */ - - /* The FT_MulDiv function has been optimized thanks to ideas from */ - /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */ - /* a rather common case when everything fits within 32-bits. */ + /* The FT_MulDiv function has been optimized thanks to ideas from */ + /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */ + /* a rather common case when everything fits within 32-bits. */ /* */ /* We compute 'a*b+c/2', then divide it by 'c'. (positive values) */ /* */ @@ -371,17 +369,24 @@ /* */ /* ( a + b ) / 2 <= sqrt( X - c/2 ) */ /* */ - /* where X = 2^31 - 1. Now we replace sqrt with a linear function */ - /* that is smaller or equal in the entire range of c from 0 to X; */ - /* it should be equal to sqrt(X) and sqrt(X/2) at the range termini. */ + /* where X = 2^32 - 1, the maximun unsigned 32-bit value, and using */ + /* unsigned arithmetic. Now we replace sqrt with a linear function */ + /* that is smaller or equal in the entire range of c from 0 to X/2; */ + /* it should be equal to sqrt(X) and sqrt(3X/4) at the termini. */ /* Substituting the linear solution and explicit numbers we get */ /* */ - /* a + b <= 92681.9 - c / 79108.95 */ + /* a + b <= 131071.99 - c / 122291.84 */ /* */ - /* In practice we use a faster and even stronger inequality */ + /* In practice we should use a faster and even stronger inequality */ /* */ - /* a + b <= 92681 - (c >> 16) */ + /* a + b <= 131071 - (c >> 16) */ /* */ + /* or, alternatively, */ + /* */ + /* a + b <= 129895 - (c >> 17) */ + /* */ + + /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Long ) FT_MulDiv( FT_Long a, @@ -402,8 +407,8 @@ if ( c == 0 ) a = 0x7FFFFFFFL; - else if ( (FT_ULong)a + (FT_ULong)b <= 92681UL - ( c >> 16 ) ) - a = ( a * b + ( c >> 1 ) ) / c; + else if ( (FT_ULong)a + b <= 129895UL - ( c >> 17 ) ) + a = ( (FT_ULong)a * b + ( c >> 1 ) ) / c; else { @@ -440,8 +445,8 @@ if ( c == 0 ) a = 0x7FFFFFFFL; - else if ( (FT_ULong)a + (FT_ULong)b <= 92681UL ) - a = a * b / c; + else if ( (FT_ULong)a + b <= 131071UL ) + a = (FT_ULong)a * b / c; else {