[Pixman] [PATCH 1/3] Round fixed-point multiplication

Søren Sandmann sandmann at cs.au.dk
Wed Nov 21 22:57:45 PST 2012


From: Søren Sandmann Pedersen <ssp at redhat.com>

After two fixed-point numbers are multiplied, the result is shifted
into place, but up until now pixman has simply discarded the low-order
bits instead of rounding to the closest number.

Fix that by adding 0x8000 (or 0x2 in one place) before shifting and
update the test checksums to match.
---
 pixman/pixman-matrix.c |   10 +++++-----
 test/affine-test.c     |    6 +++---
 test/rotate-test.c     |    2 +-
 test/scaling-test.c    |    6 +++---
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/pixman/pixman-matrix.c b/pixman/pixman-matrix.c
index d2ab609..cd2f1b5 100644
--- a/pixman/pixman-matrix.c
+++ b/pixman/pixman-matrix.c
@@ -62,7 +62,7 @@ pixman_transform_point_3d (const struct pixman_transform *transform,
 	{
 	    partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
 	               (pixman_fixed_48_16_t) vector->vector[i]);
-	    v += partial >> 16;
+	    v += (partial + 0x8000) >> 16;
 	}
 	
 	if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
@@ -96,16 +96,16 @@ pixman_transform_point (const struct pixman_transform *transform,
 	{
 	    partial = ((pixman_fixed_32_32_t) transform->matrix[j][i] *
 	               (pixman_fixed_32_32_t) vector->vector[i]);
-	    v[j] += partial >> 2;
+	    v[j] += (partial + 2) >> 2;
 	}
     }
     
-    if (!(v[2] >> 16))
+    if (!((v[2] + 0x8000) >> 16))
 	return FALSE;
 
     for (j = 0; j < 2; j++)
     {
-	quo = v[j] / (v[2] >> 16);
+	quo = v[j] / ((v[2] + 0x8000) >> 16);
 	if (quo > pixman_max_fixed_48_16 || quo < pixman_min_fixed_48_16)
 	    return FALSE;
 	vector->vector[j] = (pixman_fixed_t) quo;
@@ -138,7 +138,7 @@ pixman_transform_multiply (struct pixman_transform *      dst,
 		    (pixman_fixed_32_32_t) l->matrix[dy][o] *
 		    (pixman_fixed_32_32_t) r->matrix[o][dx];
 
-		v += partial >> 16;
+		v += (partial + 0x8000) >> 16;
 	    }
 
 	    if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
diff --git a/test/affine-test.c b/test/affine-test.c
index 7bc28b4..daa86c8 100644
--- a/test/affine-test.c
+++ b/test/affine-test.c
@@ -310,11 +310,11 @@ test_composite (int      testnum,
 }
 
 #if BILINEAR_INTERPOLATION_BITS == 8
-#define CHECKSUM 0x1EF2175A
+#define CHECKSUM 0x344413F0
 #elif BILINEAR_INTERPOLATION_BITS == 7
-#define CHECKSUM 0x74050F50
+#define CHECKSUM 0xC8181A76
 #elif BILINEAR_INTERPOLATION_BITS == 4
-#define CHECKSUM 0x4362EAE8
+#define CHECKSUM 0xD672A457
 #else
 #define CHECKSUM 0x00000000
 #endif
diff --git a/test/rotate-test.c b/test/rotate-test.c
index d63a289..a0488ef 100644
--- a/test/rotate-test.c
+++ b/test/rotate-test.c
@@ -108,6 +108,6 @@ int
 main (int argc, const char *argv[])
 {
     return fuzzer_test_main ("rotate", 15000,
-			     0x03A24D51,
+			     0x5236FD9F,
 			     test_transform, argc, argv);
 }
diff --git a/test/scaling-test.c b/test/scaling-test.c
index 2736123..0354103 100644
--- a/test/scaling-test.c
+++ b/test/scaling-test.c
@@ -380,11 +380,11 @@ test_composite (int      testnum,
 }
 
 #if BILINEAR_INTERPOLATION_BITS == 8
-#define CHECKSUM 0x8D3A7539
+#define CHECKSUM 0x107B67ED
 #elif BILINEAR_INTERPOLATION_BITS == 7
-#define CHECKSUM 0x03A23E0C
+#define CHECKSUM 0x30EC0CF0
 #elif BILINEAR_INTERPOLATION_BITS == 4
-#define CHECKSUM 0xE96D1A5E
+#define CHECKSUM 0x87B496BC
 #else
 #define CHECKSUM 0x00000000
 #endif
-- 
1.7.4



More information about the Pixman mailing list