1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifndef VG_INT_MAT3X3_H
29#define VG_INT_MAT3X3_H
30
31typedef struct {
32 float m[3][3]; /* [y][x] */
33} VG_MAT3X3_T;
34
35extern void vg_mat3x3_set_identity(VG_MAT3X3_T *a);
36extern void vg_mat3x3_set_clean(VG_MAT3X3_T *a, const float *matrix, bool force_affine);
37extern void vg_mat3x3_get(const VG_MAT3X3_T *a, float *matrix);
38extern bool vg_mat3x3_identical(const VG_MAT3X3_T *a, const VG_MAT3X3_T *b);
39
40extern void vg_mat3x3_mul(VG_MAT3X3_T *a, const VG_MAT3X3_T *b, const VG_MAT3X3_T *c);
41
42/*
43 Preconditions:
44
45 a and b may point to the same matrix.
46
47 Postconditions:
48
49 a is set to a * b.
50*/
51
52static INLINE void vg_mat3x3_postmul(VG_MAT3X3_T *a, const VG_MAT3X3_T *b)
53{
54 VG_MAT3X3_T c;
55 vg_mat3x3_mul(&c, a, b);
56 *a = c;
57}
58
59extern void vg_mat3x3_postmul_translate(VG_MAT3X3_T *a, float x, float y);
60extern void vg_mat3x3_postmul_scale(VG_MAT3X3_T *a, float x, float y);
61extern void vg_mat3x3_postmul_shear(VG_MAT3X3_T *a, float x, float y);
62extern void vg_mat3x3_postmul_rotate(VG_MAT3X3_T *a, float angle);
63extern void vg_mat3x3_postmul_rotate_sc(VG_MAT3X3_T *a, float s, float c);
64
65/*
66 Preconditions:
67
68 a and b may point to the same matrix.
69
70 Postconditions:
71
72 a is set to b * a.
73*/
74
75static INLINE void vg_mat3x3_premul(VG_MAT3X3_T *a, const VG_MAT3X3_T *b)
76{
77 VG_MAT3X3_T c;
78 vg_mat3x3_mul(&c, b, a);
79 *a = c;
80}
81
82extern void vg_mat3x3_premul_translate(VG_MAT3X3_T *a, float x, float y);
83extern void vg_mat3x3_premul_scale(VG_MAT3X3_T *a, float x, float y);
84extern void vg_mat3x3_premul_shear(VG_MAT3X3_T *a, float x, float y);
85extern void vg_mat3x3_premul_rotate(VG_MAT3X3_T *a, float angle);
86extern void vg_mat3x3_premul_rotate_sc(VG_MAT3X3_T *a, float s, float c);
87
88extern bool vg_mat3x3_is_affine(const VG_MAT3X3_T *a);
89
90/* it is possible to start with an affine matrix, apply only affine-preserving
91 * transformations, and then end up with a matrix where vg_mat3x3_is_affine
92 * returns false. this is because the bottom row of the matrix can end up
93 * containing nans if infinities or nans crop up in the calculations
94 *
95 * this is why i vcos_assert(vg_mat3x3_is_affine_or_nans) rather than just
96 * vcos_assert(vg_mat3x3_is_affine) in various places. todo: i think this could
97 * be fixed by having special affine versions of the various multiply functions
98 * that don't touch the bottom row at all, but is it worth it? */
99extern bool vg_mat3x3_is_affine_or_nans(const VG_MAT3X3_T *a);
100
101extern float vg_mat3x3_det(const VG_MAT3X3_T *a);
102extern float vg_mat3x3_affine_det(const VG_MAT3X3_T *a);
103
104extern bool vg_mat3x3_is_invertible(const VG_MAT3X3_T *a);
105extern bool vg_mat3x3_affine_is_invertible(const VG_MAT3X3_T *a);
106
107extern void vg_mat3x3_invert(VG_MAT3X3_T *a);
108extern void vg_mat3x3_affine_invert(VG_MAT3X3_T *a);
109
110/*
111 Preconditions:
112
113 -
114
115 Postconditions:
116
117 if a is invertible, according to vg_mat3x3_is_invertible, true is returned
118 and a is inverted. otherwise, false is returned and a is untouched.
119*/
120
121static INLINE bool vg_mat3x3_try_invert(VG_MAT3X3_T *a)
122{
123 if (!vg_mat3x3_is_invertible(a)) {
124 return false;
125 }
126 vg_mat3x3_invert(a);
127 return true;
128}
129
130/*
131 Preconditions:
132
133 a must be affine (or have nans in the bad elements).
134
135 Postconditions:
136
137 if a is invertible, according to vg_mat3x3_affine_is_invertible, true is
138 returned and a is inverted. otherwise, false is returned and a is untouched.
139*/
140
141static INLINE bool vg_mat3x3_affine_try_invert(VG_MAT3X3_T *a)
142{
143 if (!vg_mat3x3_affine_is_invertible(a)) {
144 return false;
145 }
146 vg_mat3x3_affine_invert(a);
147 return true;
148}
149
150extern void vg_mat3x3_affine_transform(const VG_MAT3X3_T *a, float *x, float *y);
151extern void vg_mat3x3_affine_transform_t(const VG_MAT3X3_T *a, float *x, float *y);
152
153extern void vg_mat3x3_rsq(const VG_MAT3X3_T *a, /* only top-left 2x2 matrix used */
154 float *r, float *s0, float *s1); /* don't need q for anything atm, so not calculated */
155
156#endif
157