1 /* vim: set ts=8 sw=8 noexpandtab: */
3 // Copyright (C) 2009 Mozilla Foundation
4 // Copyright (C) 1998-2007 Marti Maria
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the Software
11 // is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 struct vector
matrix_eval(struct matrix mat
, struct vector v
)
31 result
.v
[0] = mat
.m
[0][0]*v
.v
[0] + mat
.m
[0][1]*v
.v
[1] + mat
.m
[0][2]*v
.v
[2];
32 result
.v
[1] = mat
.m
[1][0]*v
.v
[0] + mat
.m
[1][1]*v
.v
[1] + mat
.m
[1][2]*v
.v
[2];
33 result
.v
[2] = mat
.m
[2][0]*v
.v
[0] + mat
.m
[2][1]*v
.v
[1] + mat
.m
[2][2]*v
.v
[2];
37 //XXX: should probably pass by reference and we could
38 //probably reuse this computation in matrix_invert
39 float matrix_det(struct matrix mat
)
42 det
= mat
.m
[0][0]*mat
.m
[1][1]*mat
.m
[2][2] +
43 mat
.m
[0][1]*mat
.m
[1][2]*mat
.m
[2][0] +
44 mat
.m
[0][2]*mat
.m
[1][0]*mat
.m
[2][1] -
45 mat
.m
[0][0]*mat
.m
[1][2]*mat
.m
[2][1] -
46 mat
.m
[0][1]*mat
.m
[1][0]*mat
.m
[2][2] -
47 mat
.m
[0][2]*mat
.m
[1][1]*mat
.m
[2][0];
51 /* from pixman and cairo and Mathematics for Game Programmers */
52 /* lcms uses gauss-jordan elimination with partial pivoting which is
53 * less efficient and not as numerically stable. See Mathematics for
54 * Game Programmers. */
55 struct matrix
matrix_invert(struct matrix mat
)
57 struct matrix dest_mat
;
59 static int a
[3] = { 2, 2, 1 };
60 static int b
[3] = { 1, 0, 0 };
62 /* inv (A) = 1/det (A) * adj (A) */
63 float det
= matrix_det(mat
);
66 dest_mat
.invalid
= true;
70 dest_mat
.invalid
= false;
74 for (j
= 0; j
< 3; j
++) {
75 for (i
= 0; i
< 3; i
++) {
82 p
= mat
.m
[ai
][aj
] * mat
.m
[bi
][bj
] -
83 mat
.m
[ai
][bj
] * mat
.m
[bi
][aj
];
84 if (((i
+ j
) & 1) != 0)
87 dest_mat
.m
[j
][i
] = det
* p
;
93 struct matrix
matrix_identity(void)
109 struct matrix
matrix_invalid(void)
111 struct matrix inv
= matrix_identity();
119 struct matrix
matrix_multiply(struct matrix a
, struct matrix b
)
121 struct matrix result
;
124 for (dy
= 0; dy
< 3; dy
++) {
125 for (dx
= 0; dx
< 3; dx
++) {
127 for (o
= 0; o
< 3; o
++) {
128 v
+= a
.m
[dy
][o
] * b
.m
[o
][dx
];
130 result
.m
[dy
][dx
] = v
;
133 result
.invalid
= a
.invalid
|| b
.invalid
;