ref: f09326a1a6d09cee2e6c60034acd86af4c94c06f
parent: 382f3155f617f63263a2d4da1b8d92472328e238
author: Alexei Podtelezhnikov <[email protected]>
date: Tue Aug 19 20:08:38 EDT 2014
[base] Use unsigned calculation in `FT_MulDiv'. * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-08-19 Alexei Podtelezhnikov <[email protected]>
+
+ [base] Use unsigned calculation in `FT_MulDiv'.
+
+ * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range.
+
2014-08-18 Alexei Podtelezhnikov <[email protected]>
[base] Remove truncation in `FT_DivFix'.
--- 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,18 +369,25 @@
/* */
/* ( 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,
FT_Long b,
@@ -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
{