Making DALi public API typesafe using guaranteed types; uint8_t, uint32_t
[platform/core/uifw/dali-core.git] / dali / public-api / math / matrix3.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/math/matrix3.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for memcpy
23 #include <ostream>
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/math/math-utils.h>
27
28 #define S00 0
29 #define S01 1
30 #define S02 2
31 #define S10 3
32 #define S11 4
33 #define S12 5
34 #define S20 6
35 #define S21 7
36 #define S22 8
37
38 /*
39  * S00 S10 S20
40  * S01 S11 S21
41  * S02 S12 S22
42  */
43
44 namespace
45 {
46 const size_t NUM_BYTES_IN_ROW    = 3*sizeof(float);
47 const size_t NUM_BYTES_IN_MATRIX = 9*sizeof(float);
48 }
49
50 namespace Dali
51 {
52
53 const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f,
54                                 0.0f, 1.0f, 0.0f,
55                                 0.0f, 0.0f, 1.0f);
56
57 Matrix3::Matrix3()
58 {
59   float* m = AsFloat();
60   memset(m, 0, NUM_BYTES_IN_MATRIX);
61 }
62
63 Matrix3::Matrix3(const Matrix3& m)
64 {
65   memcpy( mElements, m.mElements, NUM_BYTES_IN_MATRIX );
66 }
67
68 Matrix3::Matrix3(const Matrix& matrix)
69 {
70   const float* m4 = matrix.AsFloat();
71   memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
72   memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
73   memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
74 }
75
76 Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
77 {
78   mElements[S00] = s00;
79   mElements[S01] = s01;
80   mElements[S02] = s02;
81   mElements[S10] = s10;
82   mElements[S11] = s11;
83   mElements[S12] = s12;
84   mElements[S20] = s20;
85   mElements[S21] = s21;
86   mElements[S22] = s22;
87 }
88
89
90 void Matrix3::SetIdentity()
91 {
92   memset(mElements, 0, NUM_BYTES_IN_MATRIX);
93   mElements[S00]=1.0f;
94   mElements[S11]=1.0f;
95   mElements[S22]=1.0f;
96 }
97
98 Matrix3& Matrix3::operator=( const Matrix3& matrix )
99 {
100   // no point copying if self assigning
101   if( this != &matrix )
102   {
103     memcpy( AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX );
104   }
105   return *this;
106 }
107
108 Matrix3& Matrix3::operator=( const Matrix& matrix )
109 {
110   const float* m4 = matrix.AsFloat();
111   memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
112   memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
113   memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
114   return *this;
115 }
116
117 bool Matrix3::Invert()
118 {
119   bool succeeded = false;
120
121   float cof[9];
122   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
123   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
124   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
125
126   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
127   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
128   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
129
130   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
131   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
132   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
133
134   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
135
136   // In the case where the determinant is exactly zero, the matrix is non-invertible
137   if( ! EqualsZero( det ) )
138   {
139     det = 1.0f / det;
140     for( int32_t i = 0; i < 9; i++ )
141     {
142       mElements[i] = cof[i] * det;
143     }
144     succeeded = true;
145   }
146   return succeeded;
147 }
148
149 bool Matrix3::Transpose()
150 {
151   float tmp;
152   tmp = mElements[S01]; mElements[S01] = mElements[S10]; mElements[S10]=tmp;
153   tmp = mElements[S02]; mElements[S02] = mElements[S20]; mElements[S20]=tmp;
154   tmp = mElements[S21]; mElements[S21] = mElements[S12]; mElements[S12]=tmp;
155   return true;
156 }
157
158 bool Matrix3::ScaledInverseTranspose()
159 {
160   bool succeeded = false;
161
162   float cof[9];
163   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
164   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
165   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
166
167   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
168   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
169   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
170
171   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
172   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
173   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
174
175   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
176
177   // In the case where the determinant is exactly zero, the matrix is non-invertible
178   if( ! EqualsZero( det ) )
179   {
180     // Use average rather than determinant to remove rounding to zero errors in further multiplication
181     float sum=0;
182     for(size_t i=0;i<9;i++)
183     {
184       sum+=fabsf(cof[i]);
185     }
186     float scale = 9.0f/sum; // Inverse of the average values
187     if (det < 0)
188     {
189       // Ensure the signs of the inverse are correct
190       scale = -scale;
191     }
192
193     mElements[S00] = cof[S00] * scale;
194     mElements[S01] = cof[S10] * scale;
195     mElements[S02] = cof[S20] * scale;
196
197     mElements[S10] = cof[S01] * scale;
198     mElements[S11] = cof[S11] * scale;
199     mElements[S12] = cof[S21] * scale;
200
201     mElements[S20] = cof[S02] * scale;
202     mElements[S21] = cof[S12] * scale;
203     mElements[S22] = cof[S22] * scale;
204
205     succeeded = true;
206   }
207   return succeeded;
208 }
209
210 void Matrix3::Scale(float scale)
211 {
212   mElements[S00] *= scale;
213   mElements[S01] *= scale;
214   mElements[S02] *= scale;
215   mElements[S10] *= scale;
216   mElements[S11] *= scale;
217   mElements[S12] *= scale;
218   mElements[S20] *= scale;
219   mElements[S21] *= scale;
220   mElements[S22] *= scale;
221 }
222
223 float Matrix3::Magnitude() const
224 {
225   float avg=0;
226   for(size_t i=0;i<9;i++)
227   {
228     avg+=fabsf(mElements[i]);
229   }
230   return avg/3.0f;
231 }
232
233
234 void Matrix3::Multiply( Matrix3& result, const Matrix3& lhs, const Matrix3& rhs )
235 {
236   float* temp = result.AsFloat();
237   const float* rhsPtr  = rhs.AsFloat();
238   const float* lhsPtr = lhs.AsFloat();
239
240   for( int32_t i=0; i < 3; i++ )
241   {
242     int32_t loc = i * 3;
243     int32_t loc1 = loc + 1;
244     int32_t loc2 = loc + 2;
245
246     float value0 = lhsPtr[loc];
247     float value1 = lhsPtr[loc1];
248     float value2 = lhsPtr[loc2];
249     temp[loc]  = (value0 * rhsPtr[0]) +
250                  (value1 * rhsPtr[3]) +
251                  (value2 * rhsPtr[6]);
252
253     temp[loc1] = (value0 * rhsPtr[1]) +
254                  (value1 * rhsPtr[4]) +
255                  (value2 * rhsPtr[7]);
256
257     temp[loc2] = (value0 * rhsPtr[2]) +
258                  (value1 * rhsPtr[5]) +
259                  (value2 * rhsPtr[8]);
260   }
261 }
262
263 bool Matrix3::operator==(const Matrix3 & rhs) const
264 {
265   return (
266     Equals( mElements[0], rhs.mElements[0]) &&
267     Equals( mElements[1], rhs.mElements[1]) &&
268     Equals( mElements[2], rhs.mElements[2]) &&
269     Equals( mElements[3], rhs.mElements[3]) &&
270     Equals( mElements[4], rhs.mElements[4]) &&
271     Equals( mElements[5], rhs.mElements[5]) &&
272     Equals( mElements[6], rhs.mElements[6]) &&
273     Equals( mElements[7], rhs.mElements[7]) &&
274     Equals( mElements[8], rhs.mElements[8]));
275 }
276
277 bool Matrix3::operator!=(const Matrix3& rhs) const
278 {
279   return !(*this == rhs);
280 }
281
282 std::ostream& operator<< (std::ostream& o, const Matrix3& matrix)
283 {
284   return o << "[ " << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2] << ", "
285                    << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5] << ", "
286                    << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8] << " ]";
287 }
288
289 } // namespace Dali