Round fixed-point multiplication
authorSøren Sandmann Pedersen <ssp@redhat.com>
Tue, 20 Nov 2012 08:23:51 +0000 (03:23 -0500)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Tue, 20 Nov 2012 08:23:51 +0000 (03:23 -0500)
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
test/affine-test.c
test/rotate-test.c
test/scaling-test.c

index d2ab609..cd2f1b5 100644 (file)
@@ -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)
index 7bc28b4..daa86c8 100644 (file)
@@ -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
index d63a289..a0488ef 100644 (file)
@@ -108,6 +108,6 @@ int
 main (int argc, const char *argv[])
 {
     return fuzzer_test_main ("rotate", 15000,
-                            0x03A24D51,
+                            0x5236FD9F,
                             test_transform, argc, argv);
 }
index 2736123..0354103 100644 (file)
@@ -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