[PATCH] Add matrix inversion function (uses doubles)
Keith Packard
keithp at keithp.com
Fri Nov 14 14:12:42 PST 2008
The obvious matrix inversion function, coded using doubles to avoid fiddling
with fixed point precision adventures.
---
render/matrix.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++
render/picturestr.h | 3 ++
2 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/render/matrix.c b/render/matrix.c
index a976304..6e50205 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -262,6 +262,86 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
}
}
+static const int a[3] = { 3, 3, 2 };
+static const int b[3] = { 2, 1, 1 };
+
+static void
+to_doubles (double m[3][3], const PictTransformPtr t)
+{
+ int i, j;
+
+ for (j = 0; j < 3; j++)
+ for (i = 0; i < 3; i++)
+ m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
+}
+
+static Bool
+from_doubles (PictTransformPtr t, double m[3][3])
+{
+ int i, j;
+
+ for (j = 0; j < 3; j++)
+ for (i = 0; i < 3; i++)
+ {
+ double d = m[j][i];
+ if (d < -32767.0 || d > 32767.0)
+ return FALSE;
+ t->matrix[j][i] = pixman_double_to_fixed (d);
+ }
+ return TRUE;
+}
+
+static Bool
+invert (double r[3][3], double m[3][3])
+{
+ double det, norm;
+ int i, j;
+ static int a[3] = { 2, 2, 1 };
+ static int b[3] = { 1, 0, 0 };
+
+ det = 0;
+ for (i = 0; i < 3; i++) {
+ double p;
+ int ai = a[i];
+ int bi = b[i];
+ p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]);
+ if (i == 1)
+ p = -p;
+ det += p;
+ }
+ if (det == 0)
+ return FALSE;
+ det = 1/det;
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < 3; i++) {
+ double p;
+ int ai = a[i];
+ int aj = a[j];
+ int bi = b[i];
+ int bj = b[j];
+
+ p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj];
+ if (((i + j) & 1) != 0)
+ p = -p;
+ r[j][i] = det * p;
+ }
+ }
+ return TRUE;
+}
+
+_X_EXPORT Bool
+PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src)
+{
+ double m[3][3], r[3][3];
+
+ to_doubles (m, src);
+ if (!invert (r, m))
+ return FALSE;
+ if (!from_doubles (dst, r))
+ return FALSE;
+ return TRUE;
+}
+
static Bool
within_epsilon (xFixed a, xFixed b, xFixed epsilon)
{
diff --git a/render/picturestr.h b/render/picturestr.h
index 60be68a..658e221 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -720,6 +720,9 @@ void
PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
Bool
+PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src);
+
+Bool
PictureTransformIsIdentity(PictTransform *t);
Bool
--
1.5.6.5
More information about the xorg
mailing list