MAV'RIC
small_matrix.h
1 /*******************************************************************************
2  * Copyright (c) 2009-2014, MAV'RIC Development Team
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  ******************************************************************************/
31 
32 /*******************************************************************************
33  * \file small_matrix.h
34  *
35  * \author MAV'RIC Team
36  *
37  * \brief Useful matrix functions
38  *
39  ******************************************************************************/
40 
41 
42 #ifndef SMALL_MATRIX_H_
43 #define SMALL_MATRIX_H_
44 
45 
46 #ifdef __cplusplus
47 extern "C"
48 {
49 #endif
50 
51 
52 #include <stdint.h>
53 
54 typedef struct matrix_1x1_t {
55  float v[1][1];
56 } matrix_1x1_t;
57 
58 
59 typedef struct vector_1_t {
60  float v[1];
61 } vector_1_t;
62 
63 static const matrix_1x1_t zero_1x1=
64  {.v={{0.0f}} };
65 
66 static const matrix_1x1_t ones_1x1=
67  {.v={{1.0f}} };
68 
69 static const matrix_1x1_t ident_1x1=
70  {.v={{1.0f}} };
71 
72 // create diagonal matrix
73 matrix_1x1_t static inline diag_1x1(const vector_1_t v) {
74  matrix_1x1_t result= zero_1x1;
75  result.v[0][0]=v.v[0]; return result;
76 }
77 
78 // return vector of a row
79 vector_1_t static inline row1(const matrix_1x1_t m, int32_t row) {
80  vector_1_t result= {.v={m.v[row][0]}};
81  return result;
82 }
83 
84 // return vector of a column
85 vector_1_t static inline col1(const matrix_1x1_t m, int32_t col) {
86  vector_1_t result= {.v={m.v[0][col]}};
87  return result;
88 }
89 
90 // return matrix diagonal as a vector
91 vector_1_t static inline diag_vector1(const matrix_1x1_t m) {
92  vector_1_t result= {.v={m.v[0][0]}};
93  return result;
94 }
95 
96 // transpose of a matrix
97 matrix_1x1_t static inline trans1(const matrix_1x1_t m) {
98  matrix_1x1_t result=
99  {.v={{m.v[0][0]}}};
100  return result;
101 }
102 // matrix product for 1x1 matrices
103 matrix_1x1_t static inline mmul1(const matrix_1x1_t m1, const matrix_1x1_t m2) {
104  matrix_1x1_t result=
105  {.v={{m1.v[0][0]* m2.v[0][0]}}};
106  return result;
107 }
108 
109 // scalar/matrix product for 1x1 matrices
110 matrix_1x1_t static inline smmul1(const float s, const matrix_1x1_t m) {
111  matrix_1x1_t result=
112  {.v={{s * m.v[0][0]}}};
113  return result;
114 }
115 
116 // matrix/vector product for 1x1 matrices
117 vector_1_t static inline mvmul1(const matrix_1x1_t m1, const vector_1_t vec) {
118  vector_1_t result=
119  {.v={m1.v[0][0]* vec.v[0]}};
120  return result;
121 }
122 
123 // scalar/vector product for 1x1 vectors
124 vector_1_t static inline svmul1(const float s, const vector_1_t vec) {
125  vector_1_t result=
126  {.v={s* vec.v[0]}};
127  return result;
128 }
129 
130 // tensor product for 1D vectors
131 matrix_1x1_t static inline tp1(const vector_1_t vec1, const vector_1_t vec2) {
132  matrix_1x1_t result=
133  {.v={{vec1.v[0]* vec2.v[0]}}};
134  return result;
135 }
136 
137 // scalar product for 1D vectors
138 float static inline sp1(const vector_1_t vec1, const vector_1_t vec2) {
139  return (vec1.v[0]* vec2.v[0]);
140  }
141 
142 // pointwise add for 1x1 matrices
143 matrix_1x1_t static inline madd1(const matrix_1x1_t m1, const matrix_1x1_t m2) {
144  matrix_1x1_t result=
145  {.v={{m1.v[0][0]+ m2.v[0][0]}}};
146  return result;
147 }
148 
149 // pointwise add for 1x1 vectors
150 vector_1_t static inline vadd1(const vector_1_t v1, const vector_1_t v2) {
151  vector_1_t result=
152  {.v={v1.v[0]+ v2.v[0]}};
153  return result;
154 }
155 
156 // pointwise sub for 1x1 matrices
157 matrix_1x1_t static inline msub1(const matrix_1x1_t m1, const matrix_1x1_t m2) {
158  matrix_1x1_t result=
159  {.v={{m1.v[0][0]- m2.v[0][0]}}};
160  return result;
161 }
162 
163 // pointwise sub for 1x1 vectors
164 vector_1_t static inline vsub1(const vector_1_t v1, const vector_1_t v2) {
165  vector_1_t result=
166  {.v={v1.v[0]- v2.v[0]}};
167  return result;
168 }
169 
170 // pointwise pwmul for 1x1 matrices
171 matrix_1x1_t static inline mpwmul1(const matrix_1x1_t m1, const matrix_1x1_t m2) {
172  matrix_1x1_t result=
173  {.v={{m1.v[0][0]* m2.v[0][0]}}};
174  return result;
175 }
176 
177 // pointwise pwmul for 1x1 vectors
178 vector_1_t static inline vpwmul1(const vector_1_t v1, const vector_1_t v2) {
179  vector_1_t result=
180  {.v={v1.v[0]* v2.v[0]}};
181  return result;
182 }
183 
184 //squared frobenius norm for 1x1 matrices
185 float static inline sqr_f_norm1(const matrix_1x1_t m) {
186  float result=
187  m.v[0][0]* m.v[0][0];
188  return result;
189 }
190 
191 //sum of each row for 1x1 matrices
192 vector_1_t static inline row_sum1(const matrix_1x1_t m) {
193  vector_1_t result= {.v={
194  m.v[0][0]}};
195  return result;
196 }
197 
198 //sum of each column for 1x1 matrices
199 vector_1_t static inline col_sum1(const matrix_1x1_t m) {
200  vector_1_t result= {.v={
201  m.v[0][0]}};
202  return result;
203 }
204 
205 //sum for 1D vectors
206 float static inline sum1(const vector_1_t vec) {
207  float result= vec.v[0];
208  return result;
209 }
210 
211 //trace for 1D matrices
212 float static inline trace1(const matrix_1x1_t m) {
213  return sum1(diag_vector1(m));
214 }
215 
216 //squared norm for 1D vectors
217 float static inline sqr_norm1(const vector_1_t vec) {
218  float result= vec.v[0]* vec.v[0];
219  return result;
220 }
221 
222 typedef struct matrix_2x2_t {
223  float v[2][2];
224 } matrix_2x2_t;
225 
226 
227 typedef struct vector_2_t {
228  float v[2];
229 } vector_2_t;
230 
231 static const matrix_2x2_t zero_2x2=
232  {.v={{0.0f, 0.0f},
233  {0.0f, 0.0f}} };
234 
235 static const matrix_2x2_t ones_2x2=
236  {.v={{1.0f, 1.0f},
237  {1.0f, 1.0f}} };
238 
239 static const matrix_2x2_t ident_2x2=
240  {.v={{1.0f, 0.0f},
241  {0.0f, 1.0f}} };
242 
243 // create diagonal matrix
244 matrix_2x2_t static inline diag_2x2(const vector_2_t v) {
245  matrix_2x2_t result= zero_2x2;
246  result.v[0][0]=v.v[0];result.v[1][1]=v.v[1]; return result;
247 }
248 
249 // return vector of a row
250 vector_2_t static inline row2(const matrix_2x2_t m, int32_t row) {
251  vector_2_t result= {.v={m.v[row][0], m.v[row][1]}};
252  return result;
253 }
254 
255 // return vector of a column
256 vector_2_t static inline col2(const matrix_2x2_t m, int32_t col) {
257  vector_2_t result= {.v={m.v[0][col], m.v[1][col]}};
258  return result;
259 }
260 
261 // return matrix diagonal as a vector
262 vector_2_t static inline diag_vector2(const matrix_2x2_t m) {
263  vector_2_t result= {.v={m.v[0][0], m.v[1][1]}};
264  return result;
265 }
266 
267 // transpose of a matrix
268 matrix_2x2_t static inline trans2(const matrix_2x2_t m) {
269  matrix_2x2_t result=
270  {.v={{m.v[0][0], m.v[1][0]},
271  {m.v[0][1], m.v[1][1]}}};
272  return result;
273 }
274 // matrix product for 2x2 matrices
275 matrix_2x2_t static inline mmul2(const matrix_2x2_t m1, const matrix_2x2_t m2) {
276  matrix_2x2_t result=
277  {.v={{m1.v[0][0]* m2.v[0][0]+m1.v[0][1]* m2.v[1][0], m1.v[0][0]* m2.v[0][1]+m1.v[0][1]* m2.v[1][1]},
278  {m1.v[1][0]* m2.v[0][0]+m1.v[1][1]* m2.v[1][0], m1.v[1][0]* m2.v[0][1]+m1.v[1][1]* m2.v[1][1]}}};
279  return result;
280 }
281 
282 // scalar/matrix product for 2x2 matrices
283 matrix_2x2_t static inline smmul2(const float s, const matrix_2x2_t m) {
284  matrix_2x2_t result=
285  {.v={{s * m.v[0][0], s * m.v[0][1]},
286  {s * m.v[1][0], s * m.v[1][1]}}};
287  return result;
288 }
289 
290 // matrix/vector product for 2x2 matrices
291 vector_2_t static inline mvmul2(const matrix_2x2_t m1, const vector_2_t vec) {
292  vector_2_t result=
293  {.v={m1.v[0][0]* vec.v[0]+m1.v[0][1]* vec.v[1],
294  m1.v[1][0]* vec.v[0]+m1.v[1][1]* vec.v[1]}};
295  return result;
296 }
297 
298 // scalar/vector product for 2x2 vectors
299 vector_2_t static inline svmul2(const float s, const vector_2_t vec) {
300  vector_2_t result=
301  {.v={s* vec.v[0],
302  s* vec.v[1]}};
303  return result;
304 }
305 
306 // tensor product for 2D vectors
307 matrix_2x2_t static inline tp2(const vector_2_t vec1, const vector_2_t vec2) {
308  matrix_2x2_t result=
309  {.v={{vec1.v[0]* vec2.v[0], vec1.v[0]* vec2.v[1]},
310  {vec1.v[1]* vec2.v[0], vec1.v[1]* vec2.v[1]}}};
311  return result;
312 }
313 
314 // scalar product for 2D vectors
315 float static inline sp2(const vector_2_t vec1, const vector_2_t vec2) {
316  return (vec1.v[0]* vec2.v[0]+vec1.v[1]* vec2.v[1]);
317  }
318 
319 // pointwise add for 2x2 matrices
320 matrix_2x2_t static inline madd2(const matrix_2x2_t m1, const matrix_2x2_t m2) {
321  matrix_2x2_t result=
322  {.v={{m1.v[0][0]+ m2.v[0][0], m1.v[0][1]+ m2.v[0][1]},
323  {m1.v[1][0]+ m2.v[1][0], m1.v[1][1]+ m2.v[1][1]}}};
324  return result;
325 }
326 
327 // pointwise add for 2x2 vectors
328 vector_2_t static inline vadd2(const vector_2_t v1, const vector_2_t v2) {
329  vector_2_t result=
330  {.v={v1.v[0]+ v2.v[0],
331  v1.v[1]+ v2.v[1]}};
332  return result;
333 }
334 
335 // pointwise sub for 2x2 matrices
336 matrix_2x2_t static inline msub2(const matrix_2x2_t m1, const matrix_2x2_t m2) {
337  matrix_2x2_t result=
338  {.v={{m1.v[0][0]- m2.v[0][0], m1.v[0][1]- m2.v[0][1]},
339  {m1.v[1][0]- m2.v[1][0], m1.v[1][1]- m2.v[1][1]}}};
340  return result;
341 }
342 
343 // pointwise sub for 2x2 vectors
344 vector_2_t static inline vsub2(const vector_2_t v1, const vector_2_t v2) {
345  vector_2_t result=
346  {.v={v1.v[0]- v2.v[0],
347  v1.v[1]- v2.v[1]}};
348  return result;
349 }
350 
351 // pointwise pwmul for 2x2 matrices
352 matrix_2x2_t static inline mpwmul2(const matrix_2x2_t m1, const matrix_2x2_t m2) {
353  matrix_2x2_t result=
354  {.v={{m1.v[0][0]* m2.v[0][0], m1.v[0][1]* m2.v[0][1]},
355  {m1.v[1][0]* m2.v[1][0], m1.v[1][1]* m2.v[1][1]}}};
356  return result;
357 }
358 
359 // pointwise pwmul for 2x2 vectors
360 vector_2_t static inline vpwmul2(const vector_2_t v1, const vector_2_t v2) {
361  vector_2_t result=
362  {.v={v1.v[0]* v2.v[0],
363  v1.v[1]* v2.v[1]}};
364  return result;
365 }
366 
367 //squared frobenius norm for 2x2 matrices
368 float static inline sqr_f_norm2(const matrix_2x2_t m) {
369  float result=
370  m.v[0][0]* m.v[0][0] + m.v[0][1]* m.v[0][1] +
371  m.v[1][0]* m.v[1][0] + m.v[1][1]* m.v[1][1];
372  return result;
373 }
374 
375 //sum of each row for 2x2 matrices
376 vector_2_t static inline row_sum2(const matrix_2x2_t m) {
377  vector_2_t result= {.v={
378  m.v[0][0] + m.v[0][1] ,
379  m.v[1][0] + m.v[1][1]}};
380  return result;
381 }
382 
383 //sum of each column for 2x2 matrices
384 vector_2_t static inline col_sum2(const matrix_2x2_t m) {
385  vector_2_t result= {.v={
386  m.v[0][0] + m.v[1][0] ,
387  m.v[0][1] + m.v[1][1]}};
388  return result;
389 }
390 
391 //sum for 2D vectors
392 float static inline sum2(const vector_2_t vec) {
393  float result= vec.v[0] + vec.v[1];
394  return result;
395 }
396 
397 //trace for 2D matrices
398 float static inline trace2(const matrix_2x2_t m) {
399  return sum2(diag_vector2(m));
400 }
401 
402 //squared norm for 2D vectors
403 float static inline sqr_norm2(const vector_2_t vec) {
404  float result= vec.v[0]* vec.v[0] + vec.v[1]* vec.v[1];
405  return result;
406 }
407 
408 typedef struct matrix_3x3_t {
409  float v[3][3];
410 } matrix_3x3_t;
411 
412 
413 typedef struct vector_3_t {
414  float v[3];
415 } vector_3_t;
416 
417 static const matrix_3x3_t zero_3x3=
418  {.v={{0.0f, 0.0f, 0.0f},
419  {0.0f, 0.0f, 0.0f},
420  {0.0f, 0.0f, 0.0f}} };
421 
422 static const matrix_3x3_t ones_3x3=
423  {.v={{1.0f, 1.0f, 1.0f},
424  {1.0f, 1.0f, 1.0f},
425  {1.0f, 1.0f, 1.0f}} };
426 
427 static const matrix_3x3_t ident_3x3=
428  {.v={{1.0f, 0.0f, 0.0f},
429  {0.0f, 1.0f, 0.0f},
430  {0.0f, 0.0f, 1.0f}} };
431 
432 // create diagonal matrix
433 matrix_3x3_t static inline diag_3x3(const vector_3_t v) {
434  matrix_3x3_t result= zero_3x3;
435  result.v[0][0]=v.v[0];result.v[1][1]=v.v[1];result.v[2][2]=v.v[2]; return result;
436 }
437 
438 // return vector of a row
439 vector_3_t static inline row3(const matrix_3x3_t m, int32_t row) {
440  vector_3_t result= {.v={m.v[row][0], m.v[row][1], m.v[row][2]}};
441  return result;
442 }
443 
444 // return vector of a column
445 vector_3_t static inline col3(const matrix_3x3_t m, int32_t col) {
446  vector_3_t result= {.v={m.v[0][col], m.v[1][col], m.v[2][col]}};
447  return result;
448 }
449 
450 // return matrix diagonal as a vector
451 vector_3_t static inline diag_vector3(const matrix_3x3_t m) {
452  vector_3_t result= {.v={m.v[0][0], m.v[1][1], m.v[2][2]}};
453  return result;
454 }
455 
456 // transpose of a matrix
457 matrix_3x3_t static inline trans3(const matrix_3x3_t m) {
458  matrix_3x3_t result=
459  {.v={{m.v[0][0], m.v[1][0], m.v[2][0]},
460  {m.v[0][1], m.v[1][1], m.v[2][1]},
461  {m.v[0][2], m.v[1][2], m.v[2][2]}}};
462  return result;
463 }
464 // matrix product for 3x3 matrices
465 matrix_3x3_t static inline mmul3(const matrix_3x3_t m1, const matrix_3x3_t m2) {
466  matrix_3x3_t result=
467  {.v={{m1.v[0][0]* m2.v[0][0]+m1.v[0][1]* m2.v[1][0]+m1.v[0][2]* m2.v[2][0], m1.v[0][0]* m2.v[0][1]+m1.v[0][1]* m2.v[1][1]+m1.v[0][2]* m2.v[2][1], m1.v[0][0]* m2.v[0][2]+m1.v[0][1]* m2.v[1][2]+m1.v[0][2]* m2.v[2][2]},
468  {m1.v[1][0]* m2.v[0][0]+m1.v[1][1]* m2.v[1][0]+m1.v[1][2]* m2.v[2][0], m1.v[1][0]* m2.v[0][1]+m1.v[1][1]* m2.v[1][1]+m1.v[1][2]* m2.v[2][1], m1.v[1][0]* m2.v[0][2]+m1.v[1][1]* m2.v[1][2]+m1.v[1][2]* m2.v[2][2]},
469  {m1.v[2][0]* m2.v[0][0]+m1.v[2][1]* m2.v[1][0]+m1.v[2][2]* m2.v[2][0], m1.v[2][0]* m2.v[0][1]+m1.v[2][1]* m2.v[1][1]+m1.v[2][2]* m2.v[2][1], m1.v[2][0]* m2.v[0][2]+m1.v[2][1]* m2.v[1][2]+m1.v[2][2]* m2.v[2][2]}}};
470  return result;
471 }
472 
473 // scalar/matrix product for 3x3 matrices
474 matrix_3x3_t static inline smmul3(const float s, const matrix_3x3_t m) {
475  matrix_3x3_t result=
476  {.v={{s * m.v[0][0], s * m.v[0][1], s * m.v[0][2]},
477  {s * m.v[1][0], s * m.v[1][1], s * m.v[1][2]},
478  {s * m.v[2][0], s * m.v[2][1], s * m.v[2][2]}}};
479  return result;
480 }
481 
482 // matrix/vector product for 3x3 matrices
483 vector_3_t static inline mvmul3(const matrix_3x3_t m1, const vector_3_t vec) {
484  vector_3_t result=
485  {.v={m1.v[0][0]* vec.v[0]+m1.v[0][1]* vec.v[1]+m1.v[0][2]* vec.v[2],
486  m1.v[1][0]* vec.v[0]+m1.v[1][1]* vec.v[1]+m1.v[1][2]* vec.v[2],
487  m1.v[2][0]* vec.v[0]+m1.v[2][1]* vec.v[1]+m1.v[2][2]* vec.v[2]}};
488  return result;
489 }
490 
491 // scalar/vector product for 3x3 vectors
492 vector_3_t static inline svmul3(const float s, const vector_3_t vec) {
493  vector_3_t result=
494  {.v={s* vec.v[0],
495  s* vec.v[1],
496  s* vec.v[2]}};
497  return result;
498 }
499 
500 // tensor product for 3D vectors
501 matrix_3x3_t static inline tp3(const vector_3_t vec1, const vector_3_t vec2) {
502  matrix_3x3_t result=
503  {.v={{vec1.v[0]* vec2.v[0], vec1.v[0]* vec2.v[1], vec1.v[0]* vec2.v[2]},
504  {vec1.v[1]* vec2.v[0], vec1.v[1]* vec2.v[1], vec1.v[1]* vec2.v[2]},
505  {vec1.v[2]* vec2.v[0], vec1.v[2]* vec2.v[1], vec1.v[2]* vec2.v[2]}}};
506  return result;
507 }
508 
509 // scalar product for 3D vectors
510 float static inline sp3(const vector_3_t vec1, const vector_3_t vec2) {
511  return (vec1.v[0]* vec2.v[0]+vec1.v[1]* vec2.v[1]+vec1.v[2]* vec2.v[2]);
512  }
513 
514 // pointwise add for 3x3 matrices
515 matrix_3x3_t static inline madd3(const matrix_3x3_t m1, const matrix_3x3_t m2) {
516  matrix_3x3_t result=
517  {.v={{m1.v[0][0]+ m2.v[0][0], m1.v[0][1]+ m2.v[0][1], m1.v[0][2]+ m2.v[0][2]},
518  {m1.v[1][0]+ m2.v[1][0], m1.v[1][1]+ m2.v[1][1], m1.v[1][2]+ m2.v[1][2]},
519  {m1.v[2][0]+ m2.v[2][0], m1.v[2][1]+ m2.v[2][1], m1.v[2][2]+ m2.v[2][2]}}};
520  return result;
521 }
522 
523 // pointwise add for 3x3 vectors
524 vector_3_t static inline vadd3(const vector_3_t v1, const vector_3_t v2) {
525  vector_3_t result=
526  {.v={v1.v[0]+ v2.v[0],
527  v1.v[1]+ v2.v[1],
528  v1.v[2]+ v2.v[2]}};
529  return result;
530 }
531 
532 // pointwise sub for 3x3 matrices
533 matrix_3x3_t static inline msub3(const matrix_3x3_t m1, const matrix_3x3_t m2) {
534  matrix_3x3_t result=
535  {.v={{m1.v[0][0]- m2.v[0][0], m1.v[0][1]- m2.v[0][1], m1.v[0][2]- m2.v[0][2]},
536  {m1.v[1][0]- m2.v[1][0], m1.v[1][1]- m2.v[1][1], m1.v[1][2]- m2.v[1][2]},
537  {m1.v[2][0]- m2.v[2][0], m1.v[2][1]- m2.v[2][1], m1.v[2][2]- m2.v[2][2]}}};
538  return result;
539 }
540 
541 // pointwise sub for 3x3 vectors
542 vector_3_t static inline vsub3(const vector_3_t v1, const vector_3_t v2) {
543  vector_3_t result=
544  {.v={v1.v[0]- v2.v[0],
545  v1.v[1]- v2.v[1],
546  v1.v[2]- v2.v[2]}};
547  return result;
548 }
549 
550 // pointwise pwmul for 3x3 matrices
551 matrix_3x3_t static inline mpwmul3(const matrix_3x3_t m1, const matrix_3x3_t m2) {
552  matrix_3x3_t result=
553  {.v={{m1.v[0][0]* m2.v[0][0], m1.v[0][1]* m2.v[0][1], m1.v[0][2]* m2.v[0][2]},
554  {m1.v[1][0]* m2.v[1][0], m1.v[1][1]* m2.v[1][1], m1.v[1][2]* m2.v[1][2]},
555  {m1.v[2][0]* m2.v[2][0], m1.v[2][1]* m2.v[2][1], m1.v[2][2]* m2.v[2][2]}}};
556  return result;
557 }
558 
559 // pointwise pwmul for 3x3 vectors
560 vector_3_t static inline vpwmul3(const vector_3_t v1, const vector_3_t v2) {
561  vector_3_t result=
562  {.v={v1.v[0]* v2.v[0],
563  v1.v[1]* v2.v[1],
564  v1.v[2]* v2.v[2]}};
565  return result;
566 }
567 
568 //squared frobenius norm for 3x3 matrices
569 float static inline sqr_f_norm3(const matrix_3x3_t m) {
570  float result=
571  m.v[0][0]* m.v[0][0] + m.v[0][1]* m.v[0][1] + m.v[0][2]* m.v[0][2] +
572  m.v[1][0]* m.v[1][0] + m.v[1][1]* m.v[1][1] + m.v[1][2]* m.v[1][2] +
573  m.v[2][0]* m.v[2][0] + m.v[2][1]* m.v[2][1] + m.v[2][2]* m.v[2][2];
574  return result;
575 }
576 
577 //sum of each row for 3x3 matrices
578 vector_3_t static inline row_sum3(const matrix_3x3_t m) {
579  vector_3_t result= {.v={
580  m.v[0][0] + m.v[0][1] + m.v[0][2] ,
581  m.v[1][0] + m.v[1][1] + m.v[1][2] ,
582  m.v[2][0] + m.v[2][1] + m.v[2][2]}};
583  return result;
584 }
585 
586 //sum of each column for 3x3 matrices
587 vector_3_t static inline col_sum3(const matrix_3x3_t m) {
588  vector_3_t result= {.v={
589  m.v[0][0] + m.v[1][0] + m.v[2][0] ,
590  m.v[0][1] + m.v[1][1] + m.v[2][1] ,
591  m.v[0][2] + m.v[1][2] + m.v[2][2]}};
592  return result;
593 }
594 
595 //sum for 3D vectors
596 float static inline sum3(const vector_3_t vec) {
597  float result= vec.v[0] + vec.v[1] + vec.v[2];
598  return result;
599 }
600 
601 //trace for 3D matrices
602 float static inline trace3(const matrix_3x3_t m) {
603  return sum3(diag_vector3(m));
604 }
605 
606 //squared norm for 3D vectors
607 float static inline sqr_norm3(const vector_3_t vec) {
608  float result= vec.v[0]* vec.v[0] + vec.v[1]* vec.v[1] + vec.v[2]* vec.v[2];
609  return result;
610 }
611 
612 typedef struct matrix_4x4_t {
613  float v[4][4];
614 } matrix_4x4_t;
615 
616 
617 typedef struct vector_4_t {
618  float v[4];
619 } vector_4_t;
620 
621 static const matrix_4x4_t zero_4x4=
622  {.v={{0.0f, 0.0f, 0.0f, 0.0f},
623  {0.0f, 0.0f, 0.0f, 0.0f},
624  {0.0f, 0.0f, 0.0f, 0.0f},
625  {0.0f, 0.0f, 0.0f, 0.0f}} };
626 
627 static const matrix_4x4_t ones_4x4=
628  {.v={{1.0f, 1.0f, 1.0f, 1.0f},
629  {1.0f, 1.0f, 1.0f, 1.0f},
630  {1.0f, 1.0f, 1.0f, 1.0f},
631  {1.0f, 1.0f, 1.0f, 1.0f}} };
632 
633 static const matrix_4x4_t ident_4x4=
634  {.v={{1.0f, 0.0f, 0.0f, 0.0f},
635  {0.0f, 1.0f, 0.0f, 0.0f},
636  {0.0f, 0.0f, 1.0f, 0.0f},
637  {0.0f, 0.0f, 0.0f, 1.0f}} };
638 
639 // create diagonal matrix
640 matrix_4x4_t static inline diag_4x4(const vector_4_t v) {
641  matrix_4x4_t result= zero_4x4;
642  result.v[0][0]=v.v[0];result.v[1][1]=v.v[1];result.v[2][2]=v.v[2];result.v[3][3]=v.v[3]; return result;
643 }
644 
645 // return vector of a row
646 vector_4_t static inline row4(const matrix_4x4_t m, int32_t row) {
647  vector_4_t result= {.v={m.v[row][0], m.v[row][1], m.v[row][2], m.v[row][3]}};
648  return result;
649 }
650 
651 // return vector of a column
652 vector_4_t static inline col4(const matrix_4x4_t m, int32_t col) {
653  vector_4_t result= {.v={m.v[0][col], m.v[1][col], m.v[2][col], m.v[3][col]}};
654  return result;
655 }
656 
657 // return matrix diagonal as a vector
658 vector_4_t static inline diag_vector4(const matrix_4x4_t m) {
659  vector_4_t result= {.v={m.v[0][0], m.v[1][1], m.v[2][2], m.v[3][3]}};
660  return result;
661 }
662 
663 // transpose of a matrix
664 matrix_4x4_t static inline trans4(const matrix_4x4_t m) {
665  matrix_4x4_t result=
666  {.v={{m.v[0][0], m.v[1][0], m.v[2][0], m.v[3][0]},
667  {m.v[0][1], m.v[1][1], m.v[2][1], m.v[3][1]},
668  {m.v[0][2], m.v[1][2], m.v[2][2], m.v[3][2]},
669  {m.v[0][3], m.v[1][3], m.v[2][3], m.v[3][3]}}};
670  return result;
671 }
672 // matrix product for 4x4 matrices
673 matrix_4x4_t static inline mmul4(const matrix_4x4_t m1, const matrix_4x4_t m2) {
674  matrix_4x4_t result=
675  {.v={{m1.v[0][0]* m2.v[0][0]+m1.v[0][1]* m2.v[1][0]+m1.v[0][2]* m2.v[2][0]+m1.v[0][3]* m2.v[3][0], m1.v[0][0]* m2.v[0][1]+m1.v[0][1]* m2.v[1][1]+m1.v[0][2]* m2.v[2][1]+m1.v[0][3]* m2.v[3][1], m1.v[0][0]* m2.v[0][2]+m1.v[0][1]* m2.v[1][2]+m1.v[0][2]* m2.v[2][2]+m1.v[0][3]* m2.v[3][2], m1.v[0][0]* m2.v[0][3]+m1.v[0][1]* m2.v[1][3]+m1.v[0][2]* m2.v[2][3]+m1.v[0][3]* m2.v[3][3]},
676  {m1.v[1][0]* m2.v[0][0]+m1.v[1][1]* m2.v[1][0]+m1.v[1][2]* m2.v[2][0]+m1.v[1][3]* m2.v[3][0], m1.v[1][0]* m2.v[0][1]+m1.v[1][1]* m2.v[1][1]+m1.v[1][2]* m2.v[2][1]+m1.v[1][3]* m2.v[3][1], m1.v[1][0]* m2.v[0][2]+m1.v[1][1]* m2.v[1][2]+m1.v[1][2]* m2.v[2][2]+m1.v[1][3]* m2.v[3][2], m1.v[1][0]* m2.v[0][3]+m1.v[1][1]* m2.v[1][3]+m1.v[1][2]* m2.v[2][3]+m1.v[1][3]* m2.v[3][3]},
677  {m1.v[2][0]* m2.v[0][0]+m1.v[2][1]* m2.v[1][0]+m1.v[2][2]* m2.v[2][0]+m1.v[2][3]* m2.v[3][0], m1.v[2][0]* m2.v[0][1]+m1.v[2][1]* m2.v[1][1]+m1.v[2][2]* m2.v[2][1]+m1.v[2][3]* m2.v[3][1], m1.v[2][0]* m2.v[0][2]+m1.v[2][1]* m2.v[1][2]+m1.v[2][2]* m2.v[2][2]+m1.v[2][3]* m2.v[3][2], m1.v[2][0]* m2.v[0][3]+m1.v[2][1]* m2.v[1][3]+m1.v[2][2]* m2.v[2][3]+m1.v[2][3]* m2.v[3][3]},
678  {m1.v[3][0]* m2.v[0][0]+m1.v[3][1]* m2.v[1][0]+m1.v[3][2]* m2.v[2][0]+m1.v[3][3]* m2.v[3][0], m1.v[3][0]* m2.v[0][1]+m1.v[3][1]* m2.v[1][1]+m1.v[3][2]* m2.v[2][1]+m1.v[3][3]* m2.v[3][1], m1.v[3][0]* m2.v[0][2]+m1.v[3][1]* m2.v[1][2]+m1.v[3][2]* m2.v[2][2]+m1.v[3][3]* m2.v[3][2], m1.v[3][0]* m2.v[0][3]+m1.v[3][1]* m2.v[1][3]+m1.v[3][2]* m2.v[2][3]+m1.v[3][3]* m2.v[3][3]}}};
679  return result;
680 }
681 
682 // scalar/matrix product for 4x4 matrices
683 matrix_4x4_t static inline smmul4(const float s, const matrix_4x4_t m) {
684  matrix_4x4_t result=
685  {.v={{s * m.v[0][0], s * m.v[0][1], s * m.v[0][2], s * m.v[0][3]},
686  {s * m.v[1][0], s * m.v[1][1], s * m.v[1][2], s * m.v[1][3]},
687  {s * m.v[2][0], s * m.v[2][1], s * m.v[2][2], s * m.v[2][3]},
688  {s * m.v[3][0], s * m.v[3][1], s * m.v[3][2], s * m.v[3][3]}}};
689  return result;
690 }
691 
692 // matrix/vector product for 4x4 matrices
693 vector_4_t static inline mvmul4(const matrix_4x4_t m1, const vector_4_t vec) {
694  vector_4_t result=
695  {.v={m1.v[0][0]* vec.v[0]+m1.v[0][1]* vec.v[1]+m1.v[0][2]* vec.v[2]+m1.v[0][3]* vec.v[3],
696  m1.v[1][0]* vec.v[0]+m1.v[1][1]* vec.v[1]+m1.v[1][2]* vec.v[2]+m1.v[1][3]* vec.v[3],
697  m1.v[2][0]* vec.v[0]+m1.v[2][1]* vec.v[1]+m1.v[2][2]* vec.v[2]+m1.v[2][3]* vec.v[3],
698  m1.v[3][0]* vec.v[0]+m1.v[3][1]* vec.v[1]+m1.v[3][2]* vec.v[2]+m1.v[3][3]* vec.v[3]}};
699  return result;
700 }
701 
702 // scalar/vector product for 4x4 vectors
703 vector_4_t static inline svmul4(const float s, const vector_4_t vec) {
704  vector_4_t result=
705  {.v={s* vec.v[0],
706  s* vec.v[1],
707  s* vec.v[2],
708  s* vec.v[3]}};
709  return result;
710 }
711 
712 // tensor product for 4D vectors
713 matrix_4x4_t static inline tp4(const vector_4_t vec1, const vector_4_t vec2) {
714  matrix_4x4_t result=
715  {.v={{vec1.v[0]* vec2.v[0], vec1.v[0]* vec2.v[1], vec1.v[0]* vec2.v[2], vec1.v[0]* vec2.v[3]},
716  {vec1.v[1]* vec2.v[0], vec1.v[1]* vec2.v[1], vec1.v[1]* vec2.v[2], vec1.v[1]* vec2.v[3]},
717  {vec1.v[2]* vec2.v[0], vec1.v[2]* vec2.v[1], vec1.v[2]* vec2.v[2], vec1.v[2]* vec2.v[3]},
718  {vec1.v[3]* vec2.v[0], vec1.v[3]* vec2.v[1], vec1.v[3]* vec2.v[2], vec1.v[3]* vec2.v[3]}}};
719  return result;
720 }
721 
722 // scalar product for 4D vectors
723 float static inline sp4(const vector_4_t vec1, const vector_4_t vec2) {
724  return (vec1.v[0]* vec2.v[0]+vec1.v[1]* vec2.v[1]+vec1.v[2]* vec2.v[2]+vec1.v[3]* vec2.v[3]);
725  }
726 
727 // pointwise add for 4x4 matrices
728 matrix_4x4_t static inline madd4(const matrix_4x4_t m1, const matrix_4x4_t m2) {
729  matrix_4x4_t result=
730  {.v={{m1.v[0][0]+ m2.v[0][0], m1.v[0][1]+ m2.v[0][1], m1.v[0][2]+ m2.v[0][2], m1.v[0][3]+ m2.v[0][3]},
731  {m1.v[1][0]+ m2.v[1][0], m1.v[1][1]+ m2.v[1][1], m1.v[1][2]+ m2.v[1][2], m1.v[1][3]+ m2.v[1][3]},
732  {m1.v[2][0]+ m2.v[2][0], m1.v[2][1]+ m2.v[2][1], m1.v[2][2]+ m2.v[2][2], m1.v[2][3]+ m2.v[2][3]},
733  {m1.v[3][0]+ m2.v[3][0], m1.v[3][1]+ m2.v[3][1], m1.v[3][2]+ m2.v[3][2], m1.v[3][3]+ m2.v[3][3]}}};
734  return result;
735 }
736 
737 // pointwise add for 4x4 vectors
738 vector_4_t static inline vadd4(const vector_4_t v1, const vector_4_t v2) {
739  vector_4_t result=
740  {.v={v1.v[0]+ v2.v[0],
741  v1.v[1]+ v2.v[1],
742  v1.v[2]+ v2.v[2],
743  v1.v[3]+ v2.v[3]}};
744  return result;
745 }
746 
747 // pointwise sub for 4x4 matrices
748 matrix_4x4_t static inline msub4(const matrix_4x4_t m1, const matrix_4x4_t m2) {
749  matrix_4x4_t result=
750  {.v={{m1.v[0][0]- m2.v[0][0], m1.v[0][1]- m2.v[0][1], m1.v[0][2]- m2.v[0][2], m1.v[0][3]- m2.v[0][3]},
751  {m1.v[1][0]- m2.v[1][0], m1.v[1][1]- m2.v[1][1], m1.v[1][2]- m2.v[1][2], m1.v[1][3]- m2.v[1][3]},
752  {m1.v[2][0]- m2.v[2][0], m1.v[2][1]- m2.v[2][1], m1.v[2][2]- m2.v[2][2], m1.v[2][3]- m2.v[2][3]},
753  {m1.v[3][0]- m2.v[3][0], m1.v[3][1]- m2.v[3][1], m1.v[3][2]- m2.v[3][2], m1.v[3][3]- m2.v[3][3]}}};
754  return result;
755 }
756 
757 // pointwise sub for 4x4 vectors
758 vector_4_t static inline vsub4(const vector_4_t v1, const vector_4_t v2) {
759  vector_4_t result=
760  {.v={v1.v[0]- v2.v[0],
761  v1.v[1]- v2.v[1],
762  v1.v[2]- v2.v[2],
763  v1.v[3]- v2.v[3]}};
764  return result;
765 }
766 
767 // pointwise pwmul for 4x4 matrices
768 matrix_4x4_t static inline mpwmul4(const matrix_4x4_t m1, const matrix_4x4_t m2) {
769  matrix_4x4_t result=
770  {.v={{m1.v[0][0]* m2.v[0][0], m1.v[0][1]* m2.v[0][1], m1.v[0][2]* m2.v[0][2], m1.v[0][3]* m2.v[0][3]},
771  {m1.v[1][0]* m2.v[1][0], m1.v[1][1]* m2.v[1][1], m1.v[1][2]* m2.v[1][2], m1.v[1][3]* m2.v[1][3]},
772  {m1.v[2][0]* m2.v[2][0], m1.v[2][1]* m2.v[2][1], m1.v[2][2]* m2.v[2][2], m1.v[2][3]* m2.v[2][3]},
773  {m1.v[3][0]* m2.v[3][0], m1.v[3][1]* m2.v[3][1], m1.v[3][2]* m2.v[3][2], m1.v[3][3]* m2.v[3][3]}}};
774  return result;
775 }
776 
777 // pointwise pwmul for 4x4 vectors
778 vector_4_t static inline vpwmul4(const vector_4_t v1, const vector_4_t v2) {
779  vector_4_t result=
780  {.v={v1.v[0]* v2.v[0],
781  v1.v[1]* v2.v[1],
782  v1.v[2]* v2.v[2],
783  v1.v[3]* v2.v[3]}};
784  return result;
785 }
786 
787 //squared frobenius norm for 4x4 matrices
788 float static inline sqr_f_norm4(const matrix_4x4_t m) {
789  float result=
790  m.v[0][0]* m.v[0][0] + m.v[0][1]* m.v[0][1] + m.v[0][2]* m.v[0][2] + m.v[0][3]* m.v[0][3] +
791  m.v[1][0]* m.v[1][0] + m.v[1][1]* m.v[1][1] + m.v[1][2]* m.v[1][2] + m.v[1][3]* m.v[1][3] +
792  m.v[2][0]* m.v[2][0] + m.v[2][1]* m.v[2][1] + m.v[2][2]* m.v[2][2] + m.v[2][3]* m.v[2][3] +
793  m.v[3][0]* m.v[3][0] + m.v[3][1]* m.v[3][1] + m.v[3][2]* m.v[3][2] + m.v[3][3]* m.v[3][3];
794  return result;
795 }
796 
797 //sum of each row for 4x4 matrices
798 vector_4_t static inline row_sum4(const matrix_4x4_t m) {
799  vector_4_t result= {.v={
800  m.v[0][0] + m.v[0][1] + m.v[0][2] + m.v[0][3] ,
801  m.v[1][0] + m.v[1][1] + m.v[1][2] + m.v[1][3] ,
802  m.v[2][0] + m.v[2][1] + m.v[2][2] + m.v[2][3] ,
803  m.v[3][0] + m.v[3][1] + m.v[3][2] + m.v[3][3]}};
804  return result;
805 }
806 
807 //sum of each column for 4x4 matrices
808 vector_4_t static inline col_sum4(const matrix_4x4_t m) {
809  vector_4_t result= {.v={
810  m.v[0][0] + m.v[1][0] + m.v[2][0] + m.v[3][0] ,
811  m.v[0][1] + m.v[1][1] + m.v[2][1] + m.v[3][1] ,
812  m.v[0][2] + m.v[1][2] + m.v[2][2] + m.v[3][2] ,
813  m.v[0][3] + m.v[1][3] + m.v[2][3] + m.v[3][3]}};
814  return result;
815 }
816 
817 //sum for 4D vectors
818 float static inline sum4(const vector_4_t vec) {
819  float result= vec.v[0] + vec.v[1] + vec.v[2] + vec.v[3];
820  return result;
821 }
822 
823 //trace for 4D matrices
824 float static inline trace4(const matrix_4x4_t m) {
825  return sum4(diag_vector4(m));
826 }
827 
828 //squared norm for 4D vectors
829 float static inline sqr_norm4(const vector_4_t vec) {
830  float result= vec.v[0]* vec.v[0] + vec.v[1]* vec.v[1] + vec.v[2]* vec.v[2] + vec.v[3]* vec.v[3];
831  return result;
832 }
833 
834 typedef struct matrix_5x5_t {
835  float v[5][5];
836 } matrix_5x5_t;
837 
838 
839 typedef struct vector_5_t {
840  float v[5];
841 } vector_5_t;
842 
843 static const matrix_5x5_t zero_5x5=
844  {.v={{0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
845  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
846  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
847  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
848  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}} };
849 
850 static const matrix_5x5_t ones_5x5=
851  {.v={{1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
852  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
853  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
854  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
855  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f}} };
856 
857 static const matrix_5x5_t ident_5x5=
858  {.v={{1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
859  {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
860  {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
861  {0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
862  {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}} };
863 
864 // create diagonal matrix
865 matrix_5x5_t static inline diag_5x5(const vector_5_t v) {
866  matrix_5x5_t result= zero_5x5;
867  result.v[0][0]=v.v[0];result.v[1][1]=v.v[1];result.v[2][2]=v.v[2];result.v[3][3]=v.v[3];result.v[4][4]=v.v[4]; return result;
868 }
869 
870 // return vector of a row
871 vector_5_t static inline row5(const matrix_5x5_t m, int32_t row) {
872  vector_5_t result= {.v={m.v[row][0], m.v[row][1], m.v[row][2], m.v[row][3], m.v[row][4]}};
873  return result;
874 }
875 
876 // return vector of a column
877 vector_5_t static inline col5(const matrix_5x5_t m, int32_t col) {
878  vector_5_t result= {.v={m.v[0][col], m.v[1][col], m.v[2][col], m.v[3][col], m.v[4][col]}};
879  return result;
880 }
881 
882 // return matrix diagonal as a vector
883 vector_5_t static inline diag_vector5(const matrix_5x5_t m) {
884  vector_5_t result= {.v={m.v[0][0], m.v[1][1], m.v[2][2], m.v[3][3], m.v[4][4]}};
885  return result;
886 }
887 
888 // transpose of a matrix
889 matrix_5x5_t static inline trans5(const matrix_5x5_t m) {
890  matrix_5x5_t result=
891  {.v={{m.v[0][0], m.v[1][0], m.v[2][0], m.v[3][0], m.v[4][0]},
892  {m.v[0][1], m.v[1][1], m.v[2][1], m.v[3][1], m.v[4][1]},
893  {m.v[0][2], m.v[1][2], m.v[2][2], m.v[3][2], m.v[4][2]},
894  {m.v[0][3], m.v[1][3], m.v[2][3], m.v[3][3], m.v[4][3]},
895  {m.v[0][4], m.v[1][4], m.v[2][4], m.v[3][4], m.v[4][4]}}};
896  return result;
897 }
898 // matrix product for 5x5 matrices
899 matrix_5x5_t static inline mmul5(const matrix_5x5_t m1, const matrix_5x5_t m2) {
900  matrix_5x5_t result=
901  {.v={{m1.v[0][0]* m2.v[0][0]+m1.v[0][1]* m2.v[1][0]+m1.v[0][2]* m2.v[2][0]+m1.v[0][3]* m2.v[3][0]+m1.v[0][4]* m2.v[4][0], m1.v[0][0]* m2.v[0][1]+m1.v[0][1]* m2.v[1][1]+m1.v[0][2]* m2.v[2][1]+m1.v[0][3]* m2.v[3][1]+m1.v[0][4]* m2.v[4][1], m1.v[0][0]* m2.v[0][2]+m1.v[0][1]* m2.v[1][2]+m1.v[0][2]* m2.v[2][2]+m1.v[0][3]* m2.v[3][2]+m1.v[0][4]* m2.v[4][2], m1.v[0][0]* m2.v[0][3]+m1.v[0][1]* m2.v[1][3]+m1.v[0][2]* m2.v[2][3]+m1.v[0][3]* m2.v[3][3]+m1.v[0][4]* m2.v[4][3], m1.v[0][0]* m2.v[0][4]+m1.v[0][1]* m2.v[1][4]+m1.v[0][2]* m2.v[2][4]+m1.v[0][3]* m2.v[3][4]+m1.v[0][4]* m2.v[4][4]},
902  {m1.v[1][0]* m2.v[0][0]+m1.v[1][1]* m2.v[1][0]+m1.v[1][2]* m2.v[2][0]+m1.v[1][3]* m2.v[3][0]+m1.v[1][4]* m2.v[4][0], m1.v[1][0]* m2.v[0][1]+m1.v[1][1]* m2.v[1][1]+m1.v[1][2]* m2.v[2][1]+m1.v[1][3]* m2.v[3][1]+m1.v[1][4]* m2.v[4][1], m1.v[1][0]* m2.v[0][2]+m1.v[1][1]* m2.v[1][2]+m1.v[1][2]* m2.v[2][2]+m1.v[1][3]* m2.v[3][2]+m1.v[1][4]* m2.v[4][2], m1.v[1][0]* m2.v[0][3]+m1.v[1][1]* m2.v[1][3]+m1.v[1][2]* m2.v[2][3]+m1.v[1][3]* m2.v[3][3]+m1.v[1][4]* m2.v[4][3], m1.v[1][0]* m2.v[0][4]+m1.v[1][1]* m2.v[1][4]+m1.v[1][2]* m2.v[2][4]+m1.v[1][3]* m2.v[3][4]+m1.v[1][4]* m2.v[4][4]},
903  {m1.v[2][0]* m2.v[0][0]+m1.v[2][1]* m2.v[1][0]+m1.v[2][2]* m2.v[2][0]+m1.v[2][3]* m2.v[3][0]+m1.v[2][4]* m2.v[4][0], m1.v[2][0]* m2.v[0][1]+m1.v[2][1]* m2.v[1][1]+m1.v[2][2]* m2.v[2][1]+m1.v[2][3]* m2.v[3][1]+m1.v[2][4]* m2.v[4][1], m1.v[2][0]* m2.v[0][2]+m1.v[2][1]* m2.v[1][2]+m1.v[2][2]* m2.v[2][2]+m1.v[2][3]* m2.v[3][2]+m1.v[2][4]* m2.v[4][2], m1.v[2][0]* m2.v[0][3]+m1.v[2][1]* m2.v[1][3]+m1.v[2][2]* m2.v[2][3]+m1.v[2][3]* m2.v[3][3]+m1.v[2][4]* m2.v[4][3], m1.v[2][0]* m2.v[0][4]+m1.v[2][1]* m2.v[1][4]+m1.v[2][2]* m2.v[2][4]+m1.v[2][3]* m2.v[3][4]+m1.v[2][4]* m2.v[4][4]},
904  {m1.v[3][0]* m2.v[0][0]+m1.v[3][1]* m2.v[1][0]+m1.v[3][2]* m2.v[2][0]+m1.v[3][3]* m2.v[3][0]+m1.v[3][4]* m2.v[4][0], m1.v[3][0]* m2.v[0][1]+m1.v[3][1]* m2.v[1][1]+m1.v[3][2]* m2.v[2][1]+m1.v[3][3]* m2.v[3][1]+m1.v[3][4]* m2.v[4][1], m1.v[3][0]* m2.v[0][2]+m1.v[3][1]* m2.v[1][2]+m1.v[3][2]* m2.v[2][2]+m1.v[3][3]* m2.v[3][2]+m1.v[3][4]* m2.v[4][2], m1.v[3][0]* m2.v[0][3]+m1.v[3][1]* m2.v[1][3]+m1.v[3][2]* m2.v[2][3]+m1.v[3][3]* m2.v[3][3]+m1.v[3][4]* m2.v[4][3], m1.v[3][0]* m2.v[0][4]+m1.v[3][1]* m2.v[1][4]+m1.v[3][2]* m2.v[2][4]+m1.v[3][3]* m2.v[3][4]+m1.v[3][4]* m2.v[4][4]},
905  {m1.v[4][0]* m2.v[0][0]+m1.v[4][1]* m2.v[1][0]+m1.v[4][2]* m2.v[2][0]+m1.v[4][3]* m2.v[3][0]+m1.v[4][4]* m2.v[4][0], m1.v[4][0]* m2.v[0][1]+m1.v[4][1]* m2.v[1][1]+m1.v[4][2]* m2.v[2][1]+m1.v[4][3]* m2.v[3][1]+m1.v[4][4]* m2.v[4][1], m1.v[4][0]* m2.v[0][2]+m1.v[4][1]* m2.v[1][2]+m1.v[4][2]* m2.v[2][2]+m1.v[4][3]* m2.v[3][2]+m1.v[4][4]* m2.v[4][2], m1.v[4][0]* m2.v[0][3]+m1.v[4][1]* m2.v[1][3]+m1.v[4][2]* m2.v[2][3]+m1.v[4][3]* m2.v[3][3]+m1.v[4][4]* m2.v[4][3], m1.v[4][0]* m2.v[0][4]+m1.v[4][1]* m2.v[1][4]+m1.v[4][2]* m2.v[2][4]+m1.v[4][3]* m2.v[3][4]+m1.v[4][4]* m2.v[4][4]}}};
906  return result;
907 }
908 
909 // scalar/matrix product for 5x5 matrices
910 matrix_5x5_t static inline smmul5(const float s, const matrix_5x5_t m) {
911  matrix_5x5_t result=
912  {.v={{s * m.v[0][0], s * m.v[0][1], s * m.v[0][2], s * m.v[0][3], s * m.v[0][4]},
913  {s * m.v[1][0], s * m.v[1][1], s * m.v[1][2], s * m.v[1][3], s * m.v[1][4]},
914  {s * m.v[2][0], s * m.v[2][1], s * m.v[2][2], s * m.v[2][3], s * m.v[2][4]},
915  {s * m.v[3][0], s * m.v[3][1], s * m.v[3][2], s * m.v[3][3], s * m.v[3][4]},
916  {s * m.v[4][0], s * m.v[4][1], s * m.v[4][2], s * m.v[4][3], s * m.v[4][4]}}};
917  return result;
918 }
919 
920 // matrix/vector product for 5x5 matrices
921 vector_5_t static inline mvmul5(const matrix_5x5_t m1, const vector_5_t vec) {
922  vector_5_t result=
923  {.v={m1.v[0][0]* vec.v[0]+m1.v[0][1]* vec.v[1]+m1.v[0][2]* vec.v[2]+m1.v[0][3]* vec.v[3]+m1.v[0][4]* vec.v[4],
924  m1.v[1][0]* vec.v[0]+m1.v[1][1]* vec.v[1]+m1.v[1][2]* vec.v[2]+m1.v[1][3]* vec.v[3]+m1.v[1][4]* vec.v[4],
925  m1.v[2][0]* vec.v[0]+m1.v[2][1]* vec.v[1]+m1.v[2][2]* vec.v[2]+m1.v[2][3]* vec.v[3]+m1.v[2][4]* vec.v[4],
926  m1.v[3][0]* vec.v[0]+m1.v[3][1]* vec.v[1]+m1.v[3][2]* vec.v[2]+m1.v[3][3]* vec.v[3]+m1.v[3][4]* vec.v[4],
927  m1.v[4][0]* vec.v[0]+m1.v[4][1]* vec.v[1]+m1.v[4][2]* vec.v[2]+m1.v[4][3]* vec.v[3]+m1.v[4][4]* vec.v[4]}};
928  return result;
929 }
930 
931 // scalar/vector product for 5x5 vectors
932 vector_5_t static inline svmul5(const float s, const vector_5_t vec) {
933  vector_5_t result=
934  {.v={s* vec.v[0],
935  s* vec.v[1],
936  s* vec.v[2],
937  s* vec.v[3],
938  s* vec.v[4]}};
939  return result;
940 }
941 
942 // tensor product for 5D vectors
943 matrix_5x5_t static inline tp5(const vector_5_t vec1, const vector_5_t vec2) {
944  matrix_5x5_t result=
945  {.v={{vec1.v[0]* vec2.v[0], vec1.v[0]* vec2.v[1], vec1.v[0]* vec2.v[2], vec1.v[0]* vec2.v[3], vec1.v[0]* vec2.v[4]},
946  {vec1.v[1]* vec2.v[0], vec1.v[1]* vec2.v[1], vec1.v[1]* vec2.v[2], vec1.v[1]* vec2.v[3], vec1.v[1]* vec2.v[4]},
947  {vec1.v[2]* vec2.v[0], vec1.v[2]* vec2.v[1], vec1.v[2]* vec2.v[2], vec1.v[2]* vec2.v[3], vec1.v[2]* vec2.v[4]},
948  {vec1.v[3]* vec2.v[0], vec1.v[3]* vec2.v[1], vec1.v[3]* vec2.v[2], vec1.v[3]* vec2.v[3], vec1.v[3]* vec2.v[4]},
949  {vec1.v[4]* vec2.v[0], vec1.v[4]* vec2.v[1], vec1.v[4]* vec2.v[2], vec1.v[4]* vec2.v[3], vec1.v[4]* vec2.v[4]}}};
950  return result;
951 }
952 
953 // scalar product for 5D vectors
954 float static inline sp5(const vector_5_t vec1, const vector_5_t vec2) {
955  return (vec1.v[0]* vec2.v[0]+vec1.v[1]* vec2.v[1]+vec1.v[2]* vec2.v[2]+vec1.v[3]* vec2.v[3]+vec1.v[4]* vec2.v[4]);
956  }
957 
958 // pointwise add for 5x5 matrices
959 matrix_5x5_t static inline madd5(const matrix_5x5_t m1, const matrix_5x5_t m2) {
960  matrix_5x5_t result=
961  {.v={{m1.v[0][0]+ m2.v[0][0], m1.v[0][1]+ m2.v[0][1], m1.v[0][2]+ m2.v[0][2], m1.v[0][3]+ m2.v[0][3], m1.v[0][4]+ m2.v[0][4]},
962  {m1.v[1][0]+ m2.v[1][0], m1.v[1][1]+ m2.v[1][1], m1.v[1][2]+ m2.v[1][2], m1.v[1][3]+ m2.v[1][3], m1.v[1][4]+ m2.v[1][4]},
963  {m1.v[2][0]+ m2.v[2][0], m1.v[2][1]+ m2.v[2][1], m1.v[2][2]+ m2.v[2][2], m1.v[2][3]+ m2.v[2][3], m1.v[2][4]+ m2.v[2][4]},
964  {m1.v[3][0]+ m2.v[3][0], m1.v[3][1]+ m2.v[3][1], m1.v[3][2]+ m2.v[3][2], m1.v[3][3]+ m2.v[3][3], m1.v[3][4]+ m2.v[3][4]},
965  {m1.v[4][0]+ m2.v[4][0], m1.v[4][1]+ m2.v[4][1], m1.v[4][2]+ m2.v[4][2], m1.v[4][3]+ m2.v[4][3], m1.v[4][4]+ m2.v[4][4]}}};
966  return result;
967 }
968 
969 // pointwise add for 5x5 vectors
970 vector_5_t static inline vadd5(const vector_5_t v1, const vector_5_t v2) {
971  vector_5_t result=
972  {.v={v1.v[0]+ v2.v[0],
973  v1.v[1]+ v2.v[1],
974  v1.v[2]+ v2.v[2],
975  v1.v[3]+ v2.v[3],
976  v1.v[4]+ v2.v[4]}};
977  return result;
978 }
979 
980 // pointwise sub for 5x5 matrices
981 matrix_5x5_t static inline msub5(const matrix_5x5_t m1, const matrix_5x5_t m2) {
982  matrix_5x5_t result=
983  {.v={{m1.v[0][0]- m2.v[0][0], m1.v[0][1]- m2.v[0][1], m1.v[0][2]- m2.v[0][2], m1.v[0][3]- m2.v[0][3], m1.v[0][4]- m2.v[0][4]},
984  {m1.v[1][0]- m2.v[1][0], m1.v[1][1]- m2.v[1][1], m1.v[1][2]- m2.v[1][2], m1.v[1][3]- m2.v[1][3], m1.v[1][4]- m2.v[1][4]},
985  {m1.v[2][0]- m2.v[2][0], m1.v[2][1]- m2.v[2][1], m1.v[2][2]- m2.v[2][2], m1.v[2][3]- m2.v[2][3], m1.v[2][4]- m2.v[2][4]},
986  {m1.v[3][0]- m2.v[3][0], m1.v[3][1]- m2.v[3][1], m1.v[3][2]- m2.v[3][2], m1.v[3][3]- m2.v[3][3], m1.v[3][4]- m2.v[3][4]},
987  {m1.v[4][0]- m2.v[4][0], m1.v[4][1]- m2.v[4][1], m1.v[4][2]- m2.v[4][2], m1.v[4][3]- m2.v[4][3], m1.v[4][4]- m2.v[4][4]}}};
988  return result;
989 }
990 
991 // pointwise sub for 5x5 vectors
992 vector_5_t static inline vsub5(const vector_5_t v1, const vector_5_t v2) {
993  vector_5_t result=
994  {.v={v1.v[0]- v2.v[0],
995  v1.v[1]- v2.v[1],
996  v1.v[2]- v2.v[2],
997  v1.v[3]- v2.v[3],
998  v1.v[4]- v2.v[4]}};
999  return result;
1000 }
1001 
1002 // pointwise pwmul for 5x5 matrices
1003 matrix_5x5_t static inline mpwmul5(const matrix_5x5_t m1, const matrix_5x5_t m2) {
1004  matrix_5x5_t result=
1005  {.v={{m1.v[0][0]* m2.v[0][0], m1.v[0][1]* m2.v[0][1], m1.v[0][2]* m2.v[0][2], m1.v[0][3]* m2.v[0][3], m1.v[0][4]* m2.v[0][4]},
1006  {m1.v[1][0]* m2.v[1][0], m1.v[1][1]* m2.v[1][1], m1.v[1][2]* m2.v[1][2], m1.v[1][3]* m2.v[1][3], m1.v[1][4]* m2.v[1][4]},
1007  {m1.v[2][0]* m2.v[2][0], m1.v[2][1]* m2.v[2][1], m1.v[2][2]* m2.v[2][2], m1.v[2][3]* m2.v[2][3], m1.v[2][4]* m2.v[2][4]},
1008  {m1.v[3][0]* m2.v[3][0], m1.v[3][1]* m2.v[3][1], m1.v[3][2]* m2.v[3][2], m1.v[3][3]* m2.v[3][3], m1.v[3][4]* m2.v[3][4]},
1009  {m1.v[4][0]* m2.v[4][0], m1.v[4][1]* m2.v[4][1], m1.v[4][2]* m2.v[4][2], m1.v[4][3]* m2.v[4][3], m1.v[4][4]* m2.v[4][4]}}};
1010  return result;
1011 }
1012 
1013 // pointwise pwmul for 5x5 vectors
1014 vector_5_t static inline vpwmul5(const vector_5_t v1, const vector_5_t v2) {
1015  vector_5_t result=
1016  {.v={v1.v[0]* v2.v[0],
1017  v1.v[1]* v2.v[1],
1018  v1.v[2]* v2.v[2],
1019  v1.v[3]* v2.v[3],
1020  v1.v[4]* v2.v[4]}};
1021  return result;
1022 }
1023 
1024 //squared frobenius norm for 5x5 matrices
1025 float static inline sqr_f_norm5(const matrix_5x5_t m) {
1026  float result=
1027  m.v[0][0]* m.v[0][0] + m.v[0][1]* m.v[0][1] + m.v[0][2]* m.v[0][2] + m.v[0][3]* m.v[0][3] + m.v[0][4]* m.v[0][4] +
1028  m.v[1][0]* m.v[1][0] + m.v[1][1]* m.v[1][1] + m.v[1][2]* m.v[1][2] + m.v[1][3]* m.v[1][3] + m.v[1][4]* m.v[1][4] +
1029  m.v[2][0]* m.v[2][0] + m.v[2][1]* m.v[2][1] + m.v[2][2]* m.v[2][2] + m.v[2][3]* m.v[2][3] + m.v[2][4]* m.v[2][4] +
1030  m.v[3][0]* m.v[3][0] + m.v[3][1]* m.v[3][1] + m.v[3][2]* m.v[3][2] + m.v[3][3]* m.v[3][3] + m.v[3][4]* m.v[3][4] +
1031  m.v[4][0]* m.v[4][0] + m.v[4][1]* m.v[4][1] + m.v[4][2]* m.v[4][2] + m.v[4][3]* m.v[4][3] + m.v[4][4]* m.v[4][4];
1032  return result;
1033 }
1034 
1035 //sum of each row for 5x5 matrices
1036 vector_5_t static inline row_sum5(const matrix_5x5_t m) {
1037  vector_5_t result= {.v={
1038  m.v[0][0] + m.v[0][1] + m.v[0][2] + m.v[0][3] + m.v[0][4] ,
1039  m.v[1][0] + m.v[1][1] + m.v[1][2] + m.v[1][3] + m.v[1][4] ,
1040  m.v[2][0] + m.v[2][1] + m.v[2][2] + m.v[2][3] + m.v[2][4] ,
1041  m.v[3][0] + m.v[3][1] + m.v[3][2] + m.v[3][3] + m.v[3][4] ,
1042  m.v[4][0] + m.v[4][1] + m.v[4][2] + m.v[4][3] + m.v[4][4]}};
1043  return result;
1044 }
1045 
1046 //sum of each column for 5x5 matrices
1047 vector_5_t static inline col_sum5(const matrix_5x5_t m) {
1048  vector_5_t result= {.v={
1049  m.v[0][0] + m.v[1][0] + m.v[2][0] + m.v[3][0] + m.v[4][0] ,
1050  m.v[0][1] + m.v[1][1] + m.v[2][1] + m.v[3][1] + m.v[4][1] ,
1051  m.v[0][2] + m.v[1][2] + m.v[2][2] + m.v[3][2] + m.v[4][2] ,
1052  m.v[0][3] + m.v[1][3] + m.v[2][3] + m.v[3][3] + m.v[4][3] ,
1053  m.v[0][4] + m.v[1][4] + m.v[2][4] + m.v[3][4] + m.v[4][4]}};
1054  return result;
1055 }
1056 
1057 //sum for 5D vectors
1058 float static inline sum5(const vector_5_t vec) {
1059  float result= vec.v[0] + vec.v[1] + vec.v[2] + vec.v[3] + vec.v[4];
1060  return result;
1061 }
1062 
1063 //trace for 5D matrices
1064 float static inline trace5(const matrix_5x5_t m) {
1065  return sum5(diag_vector5(m));
1066 }
1067 
1068 //squared norm for 5D vectors
1069 float static inline sqr_norm5(const vector_5_t vec) {
1070  float result= vec.v[0]* vec.v[0] + vec.v[1]* vec.v[1] + vec.v[2]* vec.v[2] + vec.v[3]* vec.v[3] + vec.v[4]* vec.v[4];
1071  return result;
1072 }
1073 
1074 typedef struct matrix_6x6_t {
1075  float v[6][6];
1076 } matrix_6x6_t;
1077 
1078 
1079 typedef struct vector_6_t {
1080  float v[6];
1081 } vector_6_t;
1082 
1083 static const matrix_6x6_t zero_6x6=
1084  {.v={{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1085  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1086  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1087  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1088  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1089  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}} };
1090 
1091 static const matrix_6x6_t ones_6x6=
1092  {.v={{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
1093  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
1094  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
1095  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
1096  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
1097  {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}} };
1098 
1099 static const matrix_6x6_t ident_6x6=
1100  {.v={{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1101  {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
1102  {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
1103  {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
1104  {0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
1105  {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}} };
1106 
1107 // create diagonal matrix
1108 matrix_6x6_t static inline diag_6x6(const vector_6_t v) {
1109  matrix_6x6_t result= zero_6x6;
1110  result.v[0][0]=v.v[0];result.v[1][1]=v.v[1];result.v[2][2]=v.v[2];result.v[3][3]=v.v[3];result.v[4][4]=v.v[4];result.v[5][5]=v.v[5]; return result;
1111 }
1112 
1113 // return vector of a row
1114 vector_6_t static inline row6(const matrix_6x6_t m, int32_t row) {
1115  vector_6_t result= {.v={m.v[row][0], m.v[row][1], m.v[row][2], m.v[row][3], m.v[row][4], m.v[row][5]}};
1116  return result;
1117 }
1118 
1119 // return vector of a column
1120 vector_6_t static inline col6(const matrix_6x6_t m, int32_t col) {
1121  vector_6_t result= {.v={m.v[0][col], m.v[1][col], m.v[2][col], m.v[3][col], m.v[4][col], m.v[5][col]}};
1122  return result;
1123 }
1124 
1125 // return matrix diagonal as a vector
1126 vector_6_t static inline diag_vector6(const matrix_6x6_t m) {
1127  vector_6_t result= {.v={m.v[0][0], m.v[1][1], m.v[2][2], m.v[3][3], m.v[4][4], m.v[5][5]}};
1128  return result;
1129 }
1130 
1131 // transpose of a matrix
1132 matrix_6x6_t static inline trans6(const matrix_6x6_t m) {
1133  matrix_6x6_t result=
1134  {.v={{m.v[0][0], m.v[1][0], m.v[2][0], m.v[3][0], m.v[4][0], m.v[5][0]},
1135  {m.v[0][1], m.v[1][1], m.v[2][1], m.v[3][1], m.v[4][1], m.v[5][1]},
1136  {m.v[0][2], m.v[1][2], m.v[2][2], m.v[3][2], m.v[4][2], m.v[5][2]},
1137  {m.v[0][3], m.v[1][3], m.v[2][3], m.v[3][3], m.v[4][3], m.v[5][3]},
1138  {m.v[0][4], m.v[1][4], m.v[2][4], m.v[3][4], m.v[4][4], m.v[5][4]},
1139  {m.v[0][5], m.v[1][5], m.v[2][5], m.v[3][5], m.v[4][5], m.v[5][5]}}};
1140  return result;
1141 }
1142 // matrix product for 6x6 matrices
1143 matrix_6x6_t static inline mmul6(const matrix_6x6_t m1, const matrix_6x6_t m2) {
1144  matrix_6x6_t result=
1145  {.v={{m1.v[0][0]* m2.v[0][0]+m1.v[0][1]* m2.v[1][0]+m1.v[0][2]* m2.v[2][0]+m1.v[0][3]* m2.v[3][0]+m1.v[0][4]* m2.v[4][0]+m1.v[0][5]* m2.v[5][0], m1.v[0][0]* m2.v[0][1]+m1.v[0][1]* m2.v[1][1]+m1.v[0][2]* m2.v[2][1]+m1.v[0][3]* m2.v[3][1]+m1.v[0][4]* m2.v[4][1]+m1.v[0][5]* m2.v[5][1], m1.v[0][0]* m2.v[0][2]+m1.v[0][1]* m2.v[1][2]+m1.v[0][2]* m2.v[2][2]+m1.v[0][3]* m2.v[3][2]+m1.v[0][4]* m2.v[4][2]+m1.v[0][5]* m2.v[5][2], m1.v[0][0]* m2.v[0][3]+m1.v[0][1]* m2.v[1][3]+m1.v[0][2]* m2.v[2][3]+m1.v[0][3]* m2.v[3][3]+m1.v[0][4]* m2.v[4][3]+m1.v[0][5]* m2.v[5][3], m1.v[0][0]* m2.v[0][4]+m1.v[0][1]* m2.v[1][4]+m1.v[0][2]* m2.v[2][4]+m1.v[0][3]* m2.v[3][4]+m1.v[0][4]* m2.v[4][4]+m1.v[0][5]* m2.v[5][4], m1.v[0][0]* m2.v[0][5]+m1.v[0][1]* m2.v[1][5]+m1.v[0][2]* m2.v[2][5]+m1.v[0][3]* m2.v[3][5]+m1.v[0][4]* m2.v[4][5]+m1.v[0][5]* m2.v[5][5]},
1146  {m1.v[1][0]* m2.v[0][0]+m1.v[1][1]* m2.v[1][0]+m1.v[1][2]* m2.v[2][0]+m1.v[1][3]* m2.v[3][0]+m1.v[1][4]* m2.v[4][0]+m1.v[1][5]* m2.v[5][0], m1.v[1][0]* m2.v[0][1]+m1.v[1][1]* m2.v[1][1]+m1.v[1][2]* m2.v[2][1]+m1.v[1][3]* m2.v[3][1]+m1.v[1][4]* m2.v[4][1]+m1.v[1][5]* m2.v[5][1], m1.v[1][0]* m2.v[0][2]+m1.v[1][1]* m2.v[1][2]+m1.v[1][2]* m2.v[2][2]+m1.v[1][3]* m2.v[3][2]+m1.v[1][4]* m2.v[4][2]+m1.v[1][5]* m2.v[5][2], m1.v[1][0]* m2.v[0][3]+m1.v[1][1]* m2.v[1][3]+m1.v[1][2]* m2.v[2][3]+m1.v[1][3]* m2.v[3][3]+m1.v[1][4]* m2.v[4][3]+m1.v[1][5]* m2.v[5][3], m1.v[1][0]* m2.v[0][4]+m1.v[1][1]* m2.v[1][4]+m1.v[1][2]* m2.v[2][4]+m1.v[1][3]* m2.v[3][4]+m1.v[1][4]* m2.v[4][4]+m1.v[1][5]* m2.v[5][4], m1.v[1][0]* m2.v[0][5]+m1.v[1][1]* m2.v[1][5]+m1.v[1][2]* m2.v[2][5]+m1.v[1][3]* m2.v[3][5]+m1.v[1][4]* m2.v[4][5]+m1.v[1][5]* m2.v[5][5]},
1147  {m1.v[2][0]* m2.v[0][0]+m1.v[2][1]* m2.v[1][0]+m1.v[2][2]* m2.v[2][0]+m1.v[2][3]* m2.v[3][0]+m1.v[2][4]* m2.v[4][0]+m1.v[2][5]* m2.v[5][0], m1.v[2][0]* m2.v[0][1]+m1.v[2][1]* m2.v[1][1]+m1.v[2][2]* m2.v[2][1]+m1.v[2][3]* m2.v[3][1]+m1.v[2][4]* m2.v[4][1]+m1.v[2][5]* m2.v[5][1], m1.v[2][0]* m2.v[0][2]+m1.v[2][1]* m2.v[1][2]+m1.v[2][2]* m2.v[2][2]+m1.v[2][3]* m2.v[3][2]+m1.v[2][4]* m2.v[4][2]+m1.v[2][5]* m2.v[5][2], m1.v[2][0]* m2.v[0][3]+m1.v[2][1]* m2.v[1][3]+m1.v[2][2]* m2.v[2][3]+m1.v[2][3]* m2.v[3][3]+m1.v[2][4]* m2.v[4][3]+m1.v[2][5]* m2.v[5][3], m1.v[2][0]* m2.v[0][4]+m1.v[2][1]* m2.v[1][4]+m1.v[2][2]* m2.v[2][4]+m1.v[2][3]* m2.v[3][4]+m1.v[2][4]* m2.v[4][4]+m1.v[2][5]* m2.v[5][4], m1.v[2][0]* m2.v[0][5]+m1.v[2][1]* m2.v[1][5]+m1.v[2][2]* m2.v[2][5]+m1.v[2][3]* m2.v[3][5]+m1.v[2][4]* m2.v[4][5]+m1.v[2][5]* m2.v[5][5]},
1148  {m1.v[3][0]* m2.v[0][0]+m1.v[3][1]* m2.v[1][0]+m1.v[3][2]* m2.v[2][0]+m1.v[3][3]* m2.v[3][0]+m1.v[3][4]* m2.v[4][0]+m1.v[3][5]* m2.v[5][0], m1.v[3][0]* m2.v[0][1]+m1.v[3][1]* m2.v[1][1]+m1.v[3][2]* m2.v[2][1]+m1.v[3][3]* m2.v[3][1]+m1.v[3][4]* m2.v[4][1]+m1.v[3][5]* m2.v[5][1], m1.v[3][0]* m2.v[0][2]+m1.v[3][1]* m2.v[1][2]+m1.v[3][2]* m2.v[2][2]+m1.v[3][3]* m2.v[3][2]+m1.v[3][4]* m2.v[4][2]+m1.v[3][5]* m2.v[5][2], m1.v[3][0]* m2.v[0][3]+m1.v[3][1]* m2.v[1][3]+m1.v[3][2]* m2.v[2][3]+m1.v[3][3]* m2.v[3][3]+m1.v[3][4]* m2.v[4][3]+m1.v[3][5]* m2.v[5][3], m1.v[3][0]* m2.v[0][4]+m1.v[3][1]* m2.v[1][4]+m1.v[3][2]* m2.v[2][4]+m1.v[3][3]* m2.v[3][4]+m1.v[3][4]* m2.v[4][4]+m1.v[3][5]* m2.v[5][4], m1.v[3][0]* m2.v[0][5]+m1.v[3][1]* m2.v[1][5]+m1.v[3][2]* m2.v[2][5]+m1.v[3][3]* m2.v[3][5]+m1.v[3][4]* m2.v[4][5]+m1.v[3][5]* m2.v[5][5]},
1149  {m1.v[4][0]* m2.v[0][0]+m1.v[4][1]* m2.v[1][0]+m1.v[4][2]* m2.v[2][0]+m1.v[4][3]* m2.v[3][0]+m1.v[4][4]* m2.v[4][0]+m1.v[4][5]* m2.v[5][0], m1.v[4][0]* m2.v[0][1]+m1.v[4][1]* m2.v[1][1]+m1.v[4][2]* m2.v[2][1]+m1.v[4][3]* m2.v[3][1]+m1.v[4][4]* m2.v[4][1]+m1.v[4][5]* m2.v[5][1], m1.v[4][0]* m2.v[0][2]+m1.v[4][1]* m2.v[1][2]+m1.v[4][2]* m2.v[2][2]+m1.v[4][3]* m2.v[3][2]+m1.v[4][4]* m2.v[4][2]+m1.v[4][5]* m2.v[5][2], m1.v[4][0]* m2.v[0][3]+m1.v[4][1]* m2.v[1][3]+m1.v[4][2]* m2.v[2][3]+m1.v[4][3]* m2.v[3][3]+m1.v[4][4]* m2.v[4][3]+m1.v[4][5]* m2.v[5][3], m1.v[4][0]* m2.v[0][4]+m1.v[4][1]* m2.v[1][4]+m1.v[4][2]* m2.v[2][4]+m1.v[4][3]* m2.v[3][4]+m1.v[4][4]* m2.v[4][4]+m1.v[4][5]* m2.v[5][4], m1.v[4][0]* m2.v[0][5]+m1.v[4][1]* m2.v[1][5]+m1.v[4][2]* m2.v[2][5]+m1.v[4][3]* m2.v[3][5]+m1.v[4][4]* m2.v[4][5]+m1.v[4][5]* m2.v[5][5]},
1150  {m1.v[5][0]* m2.v[0][0]+m1.v[5][1]* m2.v[1][0]+m1.v[5][2]* m2.v[2][0]+m1.v[5][3]* m2.v[3][0]+m1.v[5][4]* m2.v[4][0]+m1.v[5][5]* m2.v[5][0], m1.v[5][0]* m2.v[0][1]+m1.v[5][1]* m2.v[1][1]+m1.v[5][2]* m2.v[2][1]+m1.v[5][3]* m2.v[3][1]+m1.v[5][4]* m2.v[4][1]+m1.v[5][5]* m2.v[5][1], m1.v[5][0]* m2.v[0][2]+m1.v[5][1]* m2.v[1][2]+m1.v[5][2]* m2.v[2][2]+m1.v[5][3]* m2.v[3][2]+m1.v[5][4]* m2.v[4][2]+m1.v[5][5]* m2.v[5][2], m1.v[5][0]* m2.v[0][3]+m1.v[5][1]* m2.v[1][3]+m1.v[5][2]* m2.v[2][3]+m1.v[5][3]* m2.v[3][3]+m1.v[5][4]* m2.v[4][3]+m1.v[5][5]* m2.v[5][3], m1.v[5][0]* m2.v[0][4]+m1.v[5][1]* m2.v[1][4]+m1.v[5][2]* m2.v[2][4]+m1.v[5][3]* m2.v[3][4]+m1.v[5][4]* m2.v[4][4]+m1.v[5][5]* m2.v[5][4], m1.v[5][0]* m2.v[0][5]+m1.v[5][1]* m2.v[1][5]+m1.v[5][2]* m2.v[2][5]+m1.v[5][3]* m2.v[3][5]+m1.v[5][4]* m2.v[4][5]+m1.v[5][5]* m2.v[5][5]}}};
1151  return result;
1152 }
1153 
1154 // scalar/matrix product for 6x6 matrices
1155 matrix_6x6_t static inline smmul6(const float s, const matrix_6x6_t m) {
1156  matrix_6x6_t result=
1157  {.v={{s * m.v[0][0], s * m.v[0][1], s * m.v[0][2], s * m.v[0][3], s * m.v[0][4], s * m.v[0][5]},
1158  {s * m.v[1][0], s * m.v[1][1], s * m.v[1][2], s * m.v[1][3], s * m.v[1][4], s * m.v[1][5]},
1159  {s * m.v[2][0], s * m.v[2][1], s * m.v[2][2], s * m.v[2][3], s * m.v[2][4], s * m.v[2][5]},
1160  {s * m.v[3][0], s * m.v[3][1], s * m.v[3][2], s * m.v[3][3], s * m.v[3][4], s * m.v[3][5]},
1161  {s * m.v[4][0], s * m.v[4][1], s * m.v[4][2], s * m.v[4][3], s * m.v[4][4], s * m.v[4][5]},
1162  {s * m.v[5][0], s * m.v[5][1], s * m.v[5][2], s * m.v[5][3], s * m.v[5][4], s * m.v[5][5]}}};
1163  return result;
1164 }
1165 
1166 // matrix/vector product for 6x6 matrices
1167 vector_6_t static inline mvmul6(const matrix_6x6_t m1, const vector_6_t vec) {
1168  vector_6_t result=
1169  {.v={m1.v[0][0]* vec.v[0]+m1.v[0][1]* vec.v[1]+m1.v[0][2]* vec.v[2]+m1.v[0][3]* vec.v[3]+m1.v[0][4]* vec.v[4]+m1.v[0][5]* vec.v[5],
1170  m1.v[1][0]* vec.v[0]+m1.v[1][1]* vec.v[1]+m1.v[1][2]* vec.v[2]+m1.v[1][3]* vec.v[3]+m1.v[1][4]* vec.v[4]+m1.v[1][5]* vec.v[5],
1171  m1.v[2][0]* vec.v[0]+m1.v[2][1]* vec.v[1]+m1.v[2][2]* vec.v[2]+m1.v[2][3]* vec.v[3]+m1.v[2][4]* vec.v[4]+m1.v[2][5]* vec.v[5],
1172  m1.v[3][0]* vec.v[0]+m1.v[3][1]* vec.v[1]+m1.v[3][2]* vec.v[2]+m1.v[3][3]* vec.v[3]+m1.v[3][4]* vec.v[4]+m1.v[3][5]* vec.v[5],
1173  m1.v[4][0]* vec.v[0]+m1.v[4][1]* vec.v[1]+m1.v[4][2]* vec.v[2]+m1.v[4][3]* vec.v[3]+m1.v[4][4]* vec.v[4]+m1.v[4][5]* vec.v[5],
1174  m1.v[5][0]* vec.v[0]+m1.v[5][1]* vec.v[1]+m1.v[5][2]* vec.v[2]+m1.v[5][3]* vec.v[3]+m1.v[5][4]* vec.v[4]+m1.v[5][5]* vec.v[5]}};
1175  return result;
1176 }
1177 
1178 // scalar/vector product for 6x6 vectors
1179 vector_6_t static inline svmul6(const float s, const vector_6_t vec) {
1180  vector_6_t result=
1181  {.v={s* vec.v[0],
1182  s* vec.v[1],
1183  s* vec.v[2],
1184  s* vec.v[3],
1185  s* vec.v[4],
1186  s* vec.v[5]}};
1187  return result;
1188 }
1189 
1190 // tensor product for 6D vectors
1191 matrix_6x6_t static inline tp6(const vector_6_t vec1, const vector_6_t vec2) {
1192  matrix_6x6_t result=
1193  {.v={{vec1.v[0]* vec2.v[0], vec1.v[0]* vec2.v[1], vec1.v[0]* vec2.v[2], vec1.v[0]* vec2.v[3], vec1.v[0]* vec2.v[4], vec1.v[0]* vec2.v[5]},
1194  {vec1.v[1]* vec2.v[0], vec1.v[1]* vec2.v[1], vec1.v[1]* vec2.v[2], vec1.v[1]* vec2.v[3], vec1.v[1]* vec2.v[4], vec1.v[1]* vec2.v[5]},
1195  {vec1.v[2]* vec2.v[0], vec1.v[2]* vec2.v[1], vec1.v[2]* vec2.v[2], vec1.v[2]* vec2.v[3], vec1.v[2]* vec2.v[4], vec1.v[2]* vec2.v[5]},
1196  {vec1.v[3]* vec2.v[0], vec1.v[3]* vec2.v[1], vec1.v[3]* vec2.v[2], vec1.v[3]* vec2.v[3], vec1.v[3]* vec2.v[4], vec1.v[3]* vec2.v[5]},
1197  {vec1.v[4]* vec2.v[0], vec1.v[4]* vec2.v[1], vec1.v[4]* vec2.v[2], vec1.v[4]* vec2.v[3], vec1.v[4]* vec2.v[4], vec1.v[4]* vec2.v[5]},
1198  {vec1.v[5]* vec2.v[0], vec1.v[5]* vec2.v[1], vec1.v[5]* vec2.v[2], vec1.v[5]* vec2.v[3], vec1.v[5]* vec2.v[4], vec1.v[5]* vec2.v[5]}}};
1199  return result;
1200 }
1201 
1202 // scalar product for 6D vectors
1203 float static inline sp6(const vector_6_t vec1, const vector_6_t vec2) {
1204  return (vec1.v[0]* vec2.v[0]+vec1.v[1]* vec2.v[1]+vec1.v[2]* vec2.v[2]+vec1.v[3]* vec2.v[3]+vec1.v[4]* vec2.v[4]+vec1.v[5]* vec2.v[5]);
1205  }
1206 
1207 // pointwise add for 6x6 matrices
1208 matrix_6x6_t static inline madd6(const matrix_6x6_t m1, const matrix_6x6_t m2) {
1209  matrix_6x6_t result=
1210  {.v={{m1.v[0][0]+ m2.v[0][0], m1.v[0][1]+ m2.v[0][1], m1.v[0][2]+ m2.v[0][2], m1.v[0][3]+ m2.v[0][3], m1.v[0][4]+ m2.v[0][4], m1.v[0][5]+ m2.v[0][5]},
1211  {m1.v[1][0]+ m2.v[1][0], m1.v[1][1]+ m2.v[1][1], m1.v[1][2]+ m2.v[1][2], m1.v[1][3]+ m2.v[1][3], m1.v[1][4]+ m2.v[1][4], m1.v[1][5]+ m2.v[1][5]},
1212  {m1.v[2][0]+ m2.v[2][0], m1.v[2][1]+ m2.v[2][1], m1.v[2][2]+ m2.v[2][2], m1.v[2][3]+ m2.v[2][3], m1.v[2][4]+ m2.v[2][4], m1.v[2][5]+ m2.v[2][5]},
1213  {m1.v[3][0]+ m2.v[3][0], m1.v[3][1]+ m2.v[3][1], m1.v[3][2]+ m2.v[3][2], m1.v[3][3]+ m2.v[3][3], m1.v[3][4]+ m2.v[3][4], m1.v[3][5]+ m2.v[3][5]},
1214  {m1.v[4][0]+ m2.v[4][0], m1.v[4][1]+ m2.v[4][1], m1.v[4][2]+ m2.v[4][2], m1.v[4][3]+ m2.v[4][3], m1.v[4][4]+ m2.v[4][4], m1.v[4][5]+ m2.v[4][5]},
1215  {m1.v[5][0]+ m2.v[5][0], m1.v[5][1]+ m2.v[5][1], m1.v[5][2]+ m2.v[5][2], m1.v[5][3]+ m2.v[5][3], m1.v[5][4]+ m2.v[5][4], m1.v[5][5]+ m2.v[5][5]}}};
1216  return result;
1217 }
1218 
1219 // pointwise add for 6x6 vectors
1220 vector_6_t static inline vadd6(const vector_6_t v1, const vector_6_t v2) {
1221  vector_6_t result=
1222  {.v={v1.v[0]+ v2.v[0],
1223  v1.v[1]+ v2.v[1],
1224  v1.v[2]+ v2.v[2],
1225  v1.v[3]+ v2.v[3],
1226  v1.v[4]+ v2.v[4],
1227  v1.v[5]+ v2.v[5]}};
1228  return result;
1229 }
1230 
1231 // pointwise sub for 6x6 matrices
1232 matrix_6x6_t static inline msub6(const matrix_6x6_t m1, const matrix_6x6_t m2) {
1233  matrix_6x6_t result=
1234  {.v={{m1.v[0][0]- m2.v[0][0], m1.v[0][1]- m2.v[0][1], m1.v[0][2]- m2.v[0][2], m1.v[0][3]- m2.v[0][3], m1.v[0][4]- m2.v[0][4], m1.v[0][5]- m2.v[0][5]},
1235  {m1.v[1][0]- m2.v[1][0], m1.v[1][1]- m2.v[1][1], m1.v[1][2]- m2.v[1][2], m1.v[1][3]- m2.v[1][3], m1.v[1][4]- m2.v[1][4], m1.v[1][5]- m2.v[1][5]},
1236  {m1.v[2][0]- m2.v[2][0], m1.v[2][1]- m2.v[2][1], m1.v[2][2]- m2.v[2][2], m1.v[2][3]- m2.v[2][3], m1.v[2][4]- m2.v[2][4], m1.v[2][5]- m2.v[2][5]},
1237  {m1.v[3][0]- m2.v[3][0], m1.v[3][1]- m2.v[3][1], m1.v[3][2]- m2.v[3][2], m1.v[3][3]- m2.v[3][3], m1.v[3][4]- m2.v[3][4], m1.v[3][5]- m2.v[3][5]},
1238  {m1.v[4][0]- m2.v[4][0], m1.v[4][1]- m2.v[4][1], m1.v[4][2]- m2.v[4][2], m1.v[4][3]- m2.v[4][3], m1.v[4][4]- m2.v[4][4], m1.v[4][5]- m2.v[4][5]},
1239  {m1.v[5][0]- m2.v[5][0], m1.v[5][1]- m2.v[5][1], m1.v[5][2]- m2.v[5][2], m1.v[5][3]- m2.v[5][3], m1.v[5][4]- m2.v[5][4], m1.v[5][5]- m2.v[5][5]}}};
1240  return result;
1241 }
1242 
1243 // pointwise sub for 6x6 vectors
1244 vector_6_t static inline vsub6(const vector_6_t v1, const vector_6_t v2) {
1245  vector_6_t result=
1246  {.v={v1.v[0]- v2.v[0],
1247  v1.v[1]- v2.v[1],
1248  v1.v[2]- v2.v[2],
1249  v1.v[3]- v2.v[3],
1250  v1.v[4]- v2.v[4],
1251  v1.v[5]- v2.v[5]}};
1252  return result;
1253 }
1254 
1255 // pointwise pwmul for 6x6 matrices
1256 matrix_6x6_t static inline mpwmul6(const matrix_6x6_t m1, const matrix_6x6_t m2) {
1257  matrix_6x6_t result=
1258  {.v={{m1.v[0][0]* m2.v[0][0], m1.v[0][1]* m2.v[0][1], m1.v[0][2]* m2.v[0][2], m1.v[0][3]* m2.v[0][3], m1.v[0][4]* m2.v[0][4], m1.v[0][5]* m2.v[0][5]},
1259  {m1.v[1][0]* m2.v[1][0], m1.v[1][1]* m2.v[1][1], m1.v[1][2]* m2.v[1][2], m1.v[1][3]* m2.v[1][3], m1.v[1][4]* m2.v[1][4], m1.v[1][5]* m2.v[1][5]},
1260  {m1.v[2][0]* m2.v[2][0], m1.v[2][1]* m2.v[2][1], m1.v[2][2]* m2.v[2][2], m1.v[2][3]* m2.v[2][3], m1.v[2][4]* m2.v[2][4], m1.v[2][5]* m2.v[2][5]},
1261  {m1.v[3][0]* m2.v[3][0], m1.v[3][1]* m2.v[3][1], m1.v[3][2]* m2.v[3][2], m1.v[3][3]* m2.v[3][3], m1.v[3][4]* m2.v[3][4], m1.v[3][5]* m2.v[3][5]},
1262  {m1.v[4][0]* m2.v[4][0], m1.v[4][1]* m2.v[4][1], m1.v[4][2]* m2.v[4][2], m1.v[4][3]* m2.v[4][3], m1.v[4][4]* m2.v[4][4], m1.v[4][5]* m2.v[4][5]},
1263  {m1.v[5][0]* m2.v[5][0], m1.v[5][1]* m2.v[5][1], m1.v[5][2]* m2.v[5][2], m1.v[5][3]* m2.v[5][3], m1.v[5][4]* m2.v[5][4], m1.v[5][5]* m2.v[5][5]}}};
1264  return result;
1265 }
1266 
1267 // pointwise pwmul for 6x6 vectors
1268 vector_6_t static inline vpwmul6(const vector_6_t v1, const vector_6_t v2) {
1269  vector_6_t result=
1270  {.v={v1.v[0]* v2.v[0],
1271  v1.v[1]* v2.v[1],
1272  v1.v[2]* v2.v[2],
1273  v1.v[3]* v2.v[3],
1274  v1.v[4]* v2.v[4],
1275  v1.v[5]* v2.v[5]}};
1276  return result;
1277 }
1278 
1279 //squared frobenius norm for 6x6 matrices
1280 float static inline sqr_f_norm6(const matrix_6x6_t m) {
1281  float result=
1282  m.v[0][0]* m.v[0][0] + m.v[0][1]* m.v[0][1] + m.v[0][2]* m.v[0][2] + m.v[0][3]* m.v[0][3] + m.v[0][4]* m.v[0][4] + m.v[0][5]* m.v[0][5] +
1283  m.v[1][0]* m.v[1][0] + m.v[1][1]* m.v[1][1] + m.v[1][2]* m.v[1][2] + m.v[1][3]* m.v[1][3] + m.v[1][4]* m.v[1][4] + m.v[1][5]* m.v[1][5] +
1284  m.v[2][0]* m.v[2][0] + m.v[2][1]* m.v[2][1] + m.v[2][2]* m.v[2][2] + m.v[2][3]* m.v[2][3] + m.v[2][4]* m.v[2][4] + m.v[2][5]* m.v[2][5] +
1285  m.v[3][0]* m.v[3][0] + m.v[3][1]* m.v[3][1] + m.v[3][2]* m.v[3][2] + m.v[3][3]* m.v[3][3] + m.v[3][4]* m.v[3][4] + m.v[3][5]* m.v[3][5] +
1286  m.v[4][0]* m.v[4][0] + m.v[4][1]* m.v[4][1] + m.v[4][2]* m.v[4][2] + m.v[4][3]* m.v[4][3] + m.v[4][4]* m.v[4][4] + m.v[4][5]* m.v[4][5] +
1287  m.v[5][0]* m.v[5][0] + m.v[5][1]* m.v[5][1] + m.v[5][2]* m.v[5][2] + m.v[5][3]* m.v[5][3] + m.v[5][4]* m.v[5][4] + m.v[5][5]* m.v[5][5];
1288  return result;
1289 }
1290 
1291 //sum of each row for 6x6 matrices
1292 vector_6_t static inline row_sum6(const matrix_6x6_t m) {
1293  vector_6_t result= {.v={
1294  m.v[0][0] + m.v[0][1] + m.v[0][2] + m.v[0][3] + m.v[0][4] + m.v[0][5] ,
1295  m.v[1][0] + m.v[1][1] + m.v[1][2] + m.v[1][3] + m.v[1][4] + m.v[1][5] ,
1296  m.v[2][0] + m.v[2][1] + m.v[2][2] + m.v[2][3] + m.v[2][4] + m.v[2][5] ,
1297  m.v[3][0] + m.v[3][1] + m.v[3][2] + m.v[3][3] + m.v[3][4] + m.v[3][5] ,
1298  m.v[4][0] + m.v[4][1] + m.v[4][2] + m.v[4][3] + m.v[4][4] + m.v[4][5] ,
1299  m.v[5][0] + m.v[5][1] + m.v[5][2] + m.v[5][3] + m.v[5][4] + m.v[5][5]}};
1300  return result;
1301 }
1302 
1303 //sum of each column for 6x6 matrices
1304 vector_6_t static inline col_sum6(const matrix_6x6_t m) {
1305  vector_6_t result= {.v={
1306  m.v[0][0] + m.v[1][0] + m.v[2][0] + m.v[3][0] + m.v[4][0] + m.v[5][0] ,
1307  m.v[0][1] + m.v[1][1] + m.v[2][1] + m.v[3][1] + m.v[4][1] + m.v[5][1] ,
1308  m.v[0][2] + m.v[1][2] + m.v[2][2] + m.v[3][2] + m.v[4][2] + m.v[5][2] ,
1309  m.v[0][3] + m.v[1][3] + m.v[2][3] + m.v[3][3] + m.v[4][3] + m.v[5][3] ,
1310  m.v[0][4] + m.v[1][4] + m.v[2][4] + m.v[3][4] + m.v[4][4] + m.v[5][4] ,
1311  m.v[0][5] + m.v[1][5] + m.v[2][5] + m.v[3][5] + m.v[4][5] + m.v[5][5]}};
1312  return result;
1313 }
1314 
1315 //sum for 6D vectors
1316 float static inline sum6(const vector_6_t vec) {
1317  float result= vec.v[0] + vec.v[1] + vec.v[2] + vec.v[3] + vec.v[4] + vec.v[5];
1318  return result;
1319 }
1320 
1321 //trace for 6D matrices
1322 float static inline trace6(const matrix_6x6_t m) {
1323  return sum6(diag_vector6(m));
1324 }
1325 
1326 //squared norm for 6D vectors
1327 float static inline sqr_norm6(const vector_6_t vec) {
1328  float result= vec.v[0]* vec.v[0] + vec.v[1]* vec.v[1] + vec.v[2]* vec.v[2] + vec.v[3]* vec.v[3] + vec.v[4]* vec.v[4] + vec.v[5]* vec.v[5];
1329  return result;
1330 }
1331 
1332 #ifdef __cplusplus
1333 }
1334 #endif
1335 
1336 #endif
Definition: small_matrix.h:59
Definition: small_matrix.h:1074
Definition: small_matrix.h:227
Definition: small_matrix.h:222
Definition: small_matrix.h:612
Definition: small_matrix.h:834
Definition: small_matrix.h:839
Definition: small_matrix.h:408
Definition: small_matrix.h:617
Definition: small_matrix.h:54
Definition: small_matrix.h:1079
Definition: small_matrix.h:413