ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
mat.cpp
Go to the documentation of this file.
1// Copyright 2018-2023 Espressif Systems (Shanghai) PTE LTD
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <stdexcept>
16#include <string.h>
17#include "mat.h"
18#include "esp_log.h"
19
20#include "dsps_math.h"
21#include "dspm_matrix.h"
22#include <math.h>
23#include <cmath>
24#include <inttypes.h>
25
26
27
28using std::ostream;
29using std::istream;
30using std::endl;
31
32namespace dspm {
33
34float Mat::abs_tol = 1e-10;
35
36Mat::Rect::Rect(int x, int y, int width, int height)
37{
38 this->x = x;
39 this->y = y;
40 this->width = width;
41 this->height = height;
42}
43
44void Mat::Rect::resizeRect(int x, int y, int width, int height)
45{
46 this->x = x;
47 this->y = y;
48 this->width = width;
49 this->height = height;
50}
51
53{
54 return this->width * this->height;
55}
56
57Mat::Mat(float *data, int roi_rows, int roi_cols, int stride)
58{
59 this->rows = roi_rows;
60 this->cols = roi_cols;
61 this->stride = stride;
62 this->padding = stride - roi_cols;
63 this->length = this->rows * this->cols;
64 this->sub_matrix = true;
65 this->ext_buff = true;
66 this->data = data;
67}
68
70{
71 ESP_LOGD("Mat", "Mat(%i, %i)", rows, cols);
72 this->rows = rows;
73 this->cols = cols;
74 this->sub_matrix = false;
75 this->stride = cols;
76 this->padding = 0;
77 allocate();
78 memset(this->data, 0, this->length * sizeof(float));
79}
80
81Mat::Mat(float *data, int rows, int cols)
82{
83 ESP_LOGD("Mat", "Mat(data, %i, %i)", rows, cols);
84 this->rows = rows;
85 this->cols = cols;
86 this->sub_matrix = false;
87 this->stride = cols;
88 this->padding = 0;
89 this->length = this->rows * this->cols;
90 allocate();
91 this->ext_buff = false;
92 for (size_t i = 0; i < this->length; i++) {
93 this->data[i] = data[i];
94 }
95}
96
97
99{
100 this->rows = 1;
101 this->cols = 1;
102 this->sub_matrix = false;
103 this->stride = cols;
104 this->padding = 0;
105 ESP_LOGD("Mat", "Mat()");
106
107 allocate();
108 this->data[0] = 0;
109}
110
112{
113 ESP_LOGD("Mat", "~Mat(%i, %i), ext_buff=%i, data = %p", this->rows, this->cols, this->ext_buff, this->data);
114 if (false == this->ext_buff) {
115 delete[] data;
116 }
117}
118
120{
121 this->rows = m.rows;
122 this->cols = m.cols;
123 this->padding = m.padding;
124 this->stride = m.stride;
125 this->data = m.data;
126 this->sub_matrix = m.sub_matrix;
127
128 if (m.sub_matrix) {
129 this->length = m.length;
130 this->data = m.data;
131 this->ext_buff = true;
132 } else {
133 allocate();
134 memcpy(this->data, m.data, this->length * sizeof(float));
135 }
136}
137
138Mat Mat::getROI(int startRow, int startCol, int roiRows, int roiCols, int stride)
139{
140 Mat result(this->data, roiRows, roiCols, 0);
141
142 if ((startRow + roiRows) > this->rows) {
143 return result;
144 }
145 if ((startCol + roiCols) > this->cols) {
146 return result;
147 }
148
149 const int ptr_move = startRow * this->cols + startCol;
150 float *new_data_ptr = this->data + ptr_move;
151
152 result.data = new_data_ptr;
153 result.stride = stride;
154 result.padding = result.stride - result.cols;
155 return result;
156}
157
159{
160 return (getROI(rect.y, rect.x, rect.height, rect.width, this->cols));
161}
162
163Mat Mat::getROI(int startRow, int startCol, int roiRows, int roiCols)
164{
165 return (getROI(startRow, startCol, roiRows, roiCols, this->cols));
166}
167
168void Mat::Copy(const Mat &src, int row_pos, int col_pos)
169{
170 if ((row_pos + src.rows) > this->rows) {
171 return;
172 }
173 if ((col_pos + src.cols) > this->cols) {
174 return;
175 }
176
177 for (size_t r = 0; r < src.rows; r++) {
178 memcpy(&this->data[(r + row_pos) * this->stride + col_pos], &src.data[r * src.cols], src.cols * sizeof(float));
179 }
180}
181
182void Mat::CopyHead(const Mat &src)
183{
184 if (!this->ext_buff) {
185 delete[] this->data;
186 }
187 this->rows = src.rows;
188 this->cols = src.cols;
189 this->length = src.length;
190 this->padding = src.padding;
191 this->stride = src.stride;
192 this->data = src.data;
193 this->ext_buff = src.ext_buff;
194 this->sub_matrix = src.sub_matrix;
195}
196
198{
199 std::cout << "rows " << this->rows << std::endl;
200 std::cout << "cols " << this->cols << std::endl;
201 std::cout << "lenght " << this->length << std::endl;
202 std::cout << "data " << this->data << std::endl;
203 std::cout << "ext_buff " << this->ext_buff << std::endl;
204 std::cout << "sub_mat " << this->sub_matrix << std::endl;
205 std::cout << "stride " << this->stride << std::endl;
206 std::cout << "padding " << this->padding << std::endl << std::endl;
207}
208
209Mat Mat::Get(int row_start, int row_size, int col_start, int col_size)
210{
211 Mat result(row_size, col_size);
212
213 if ((row_start + row_size) > this->rows) {
214 return result;
215 }
216 if ((col_start + col_size) > this->cols) {
217 return result;
218 }
219
220 for (size_t r = 0; r < result.rows; r++) {
221 memcpy(&result.data[r * result.cols], &this->data[(r + row_start) * this->stride + col_start], result.cols * sizeof(float));
222 }
223 return result;
224}
225
227{
228 return (Get(rect.y, rect.height, rect.x, rect.width));
229}
230
232{
233 if (this == &m) {
234 return *this;
235 }
236
237 // matrix dimensions not equal
238 if (this->rows != m.rows || this->cols != m.cols) {
239 // left operand is a sub-matrix - error
240 if (this->sub_matrix) {
241 ESP_LOGE("Mat", "operator = Error for sub-matrices: operands matrices dimensions %dx%d and %dx%d do not match", this->rows, this->cols, m.rows, m.cols);
242 return *this;
243 }
244 if (!this->ext_buff) {
245 delete[] this->data;
246 }
247 this->ext_buff = false;
248 this->rows = m.rows;
249 this->cols = m.cols;
250 this->stride = this->cols;
251 this->padding = 0;
252 this->sub_matrix = false;
253 allocate();
254 }
255
256 for (int row = 0; row < this->rows; row++) {
257 memcpy(this->data + (row * this->stride), m.data + (row * m.stride), this->cols * sizeof(float));
258 }
259 return *this;
260}
261
263{
264 if ((this->rows != m.rows) || (this->cols != m.cols)) {
265 ESP_LOGW("Mat", "operator += Error: matrices do not have equal dimensions");
266 return *this;
267 }
268
269 if (this->sub_matrix || m.sub_matrix) {
270 dspm_add_f32(this->data, m.data, this->data, this->rows, this->cols, this->padding, m.padding, this->padding, 1, 1, 1);
271 } else {
272 dsps_add_f32(this->data, m.data, this->data, this->length, 1, 1, 1);
273 }
274 return *this;
275}
276
278{
279 if (this->sub_matrix) {
280 dspm_addc_f32(this->data, this->data, C, this->rows, this->cols, this->padding, this->padding, 1, 1);
281 } else {
282 dsps_addc_f32_ansi(this->data, this->data, this->length, C, 1, 1);
283 }
284 return *this;
285}
286
288{
289 if ((this->rows != m.rows) || (this->cols != m.cols)) {
290 ESP_LOGW("Mat", "operator -= Error: matrices do not have equal dimensions");
291 return *this;
292 }
293
294 if (this->sub_matrix || m.sub_matrix) {
295 dspm_sub_f32(this->data, m.data, this->data, this->rows, this->cols, this->padding, m.padding, this->padding, 1, 1, 1);
296 } else {
297 dsps_sub_f32(this->data, m.data, this->data, this->length, 1, 1, 1);
298 }
299 return *this;
300}
301
303{
304 if (this->sub_matrix) {
305 dspm_addc_f32(this->data, this->data, -C, this->rows, this->cols, this->padding, this->padding, 1, 1);
306 } else {
307 dsps_addc_f32_ansi(this->data, this->data, this->length, -C, 1, 1);
308 }
309 return *this;
310}
311
313{
314 if (this->cols != m.rows) {
315 ESP_LOGW("Mat", "operator *= Error: matrices do not have equal dimensions");
316 return *this;
317 }
318
319 if (this->sub_matrix || m.sub_matrix) {
320 Mat temp = this->Get(0, this->rows, 0, this->cols);
321 dspm_mult_ex_f32(temp.data, m.data, this->data, temp.rows, temp.cols, m.cols, temp.padding, m.padding, this->padding);
322 } else {
323 Mat temp = *this;
324 dspm_mult_f32(temp.data, m.data, this->data, temp.rows, temp.cols, m.cols);
325 }
326 return (*this);
327}
328
330{
331 if (this->sub_matrix) {
332 dspm_mulc_f32(this->data, this->data, num, this->rows, this->cols, this->padding, this->padding, 1, 1);
333 } else {
334 dsps_mulc_f32_ansi(this->data, this->data, this->length, num, 1, 1);
335 }
336 return *this;
337}
338
340{
341 if ((this->rows != B.rows) || (this->cols != B.cols)) {
342 ESP_LOGW("Mat", "operator /= Error: matrices do not have equal dimensions");
343 return *this;
344 }
345
346 for (int row = 0; row < this->rows; row++) {
347 for (int col = 0; col < this->cols; col++) {
348 (*this)(row, col) = (*this)(row, col) / B(row, col);
349 }
350 }
351 return (*this);
352}
353
355{
356 if (this->sub_matrix) {
357 dspm_mulc_f32(this->data, this->data, 1 / num, this->rows, this->cols, this->padding, this->padding, 1, 1);
358 } else {
359 dsps_mulc_f32_ansi(this->data, this->data, this->length, 1 / num, 1, 1);
360 }
361 return *this;
362}
363
365{
366 Mat temp(*this);
367 return expHelper(temp, num);
368}
369
370void Mat::swapRows(int r1, int r2)
371{
372 if ((this->rows <= r1) || (this->rows <= r2)) {
373 ESP_LOGW("Mat", "swapRows Error: row %d or %d out of matrix row %d range", r1, r2, this->rows);
374 } else {
375 for (int i = 0; i < this->cols; i++) {
376 float temp = this->data[r1 * this->stride + i];
377 this->data[r1 * this->stride + i] = this->data[r2 * this->stride + i];
378 this->data[r2 * this->stride + i] = temp;
379 }
380 }
381}
382
384{
385 Mat ret(this->cols, this->rows);
386 for (int i = 0; i < this->rows; ++i) {
387 for (int j = 0; j < this->cols; ++j) {
388 ret(j, i) = this->data[i * this->stride + j];
389 }
390 }
391 return ret;
392}
393
394Mat Mat::eye(int size)
395{
396 Mat temp(size, size);
397 for (int i = 0; i < temp.rows; ++i) {
398 for (int j = 0; j < temp.cols; ++j) {
399 if (i == j) {
400 temp(i, j) = 1;
401 } else {
402 temp(i, j) = 0;
403 }
404 }
405 }
406 return temp;
407}
408
409Mat Mat::ones(int size)
410{
411 return (ones(size, size));
412}
413
415{
416 Mat temp(rows, cols);
417 for (int row = 0; row < temp.rows; ++row) {
418 for (int col = 0; col < temp.cols; ++col) {
419 temp(row, col) = 1;
420 }
421 }
422 return temp;
423}
424
426{
427 for (int row = 0; row < this->rows; row++) {
428 memset(this->data + (row * this->stride), 0, this->cols * sizeof(float));
429 }
430}
431
432// Duplicate to Get method
433Mat Mat::block(int startRow, int startCol, int blockRows, int blockCols)
434{
435 Mat result(blockRows, blockCols);
436 for (int i = 0; i < blockRows; ++i) {
437 for (int j = 0; j < blockCols; ++j) {
438 result(i, j) = (*this)(startRow + i, startCol + j);
439 }
440 }
441 return result;
442}
443
445{
446 float sqr_norm = 0;
447 for (int i = 0; i < this->rows; ++i) {
448 for (int j = 0; j < this->cols; ++j) {
449 sqr_norm += (*this)(i, j) * (*this)(i, j);
450 }
451 }
452 sqr_norm = 1 / sqrtf(sqr_norm);
453 *this *= sqr_norm;
454}
455
456float Mat::norm(void)
457{
458 float sqr_norm = 0;
459 for (int i = 0; i < this->rows; ++i) {
460 for (int j = 0; j < this->cols; ++j) {
461 sqr_norm += (*this)(i, j) * (*this)(i, j);
462 }
463 }
464 sqr_norm = sqrtf(sqr_norm);
465 return sqr_norm;
466}
467
469{
470 // Gaussian elimination
471 for (int i = 0; i < A.rows; ++i) {
472 if (A(i, i) == 0) {
473 // pivot 0 - error
474 ESP_LOGW("Mat", "Error: the coefficient matrix has 0 as a pivot. Please fix the input and try again.");
475 Mat err_result(0, 0);
476 return err_result;
477 }
478 float a_ii = 1 / A(i, i);
479 for (int j = i + 1; j < A.rows; ++j) {
480 float a_ji = A(j, i) * a_ii;
481 for (int k = i + 1; k < A.cols; ++k) {
482 A(j, k) -= A(i, k) * a_ji;
483 if ((A(j, k) < abs_tol) && (A(j, k) > -1 * abs_tol)) {
484 A(j, k) = 0;
485 }
486 }
487 b(j, 0) -= b(i, 0) * a_ji;
488 if (A(j, 0) < abs_tol && A(j, 0) > -1 * abs_tol) {
489 A(j, 0) = 0;
490 }
491 A(j, i) = 0;
492 }
493 }
494
495 // Back substitution
496 Mat x(b.rows, 1);
497 x((x.rows - 1), 0) = b((x.rows - 1), 0) / A((x.rows - 1), (x.rows - 1));
498 if (x((x.rows - 1), 0) < abs_tol && x((x.rows - 1), 0) > -1 * abs_tol) {
499 x((x.rows - 1), 0) = 0;
500 }
501 for (int i = x.rows - 2; i >= 0; --i) {
502 float sum = 0;
503 for (int j = i + 1; j < x.rows; ++j) {
504 sum += A(i, j) * x(j, 0);
505 }
506 x(i, 0) = (b(i, 0) - sum) / A(i, i);
507 if (x(i, 0) < abs_tol && x(i, 0) > -1 * abs_tol) {
508 x(i, 0) = 0;
509 }
510 }
511 return x;
512}
513
515{
516 // optimized Gaussian elimination
517 int bandsBelow = (k - 1) / 2;
518 for (int i = 0; i < A.rows; ++i) {
519 if (A(i, i) == 0) {
520 // pivot 0 - error
521 ESP_LOGW("Mat", "Error: the coefficient matrix has 0 as a pivot. Please fix the input and try again.");
522 Mat err_result(b.rows, 1);
523 memset(err_result.data, 0, b.rows * sizeof(float));
524 return err_result;
525 }
526 float a_ii = 1 / A(i, i);
527 for (int j = i + 1; j < A.rows && j <= i + bandsBelow; ++j) {
528 int k = i + 1;
529 while ((k < A.cols) && (fabs(A(j, k)) > abs_tol)) {
530 A(j, k) -= A(i, k) * (A(j, i) * a_ii);
531 k++;
532 }
533 b(j, 0) -= b(i, 0) * (A(j, i) * a_ii);
534 A(j, i) = 0;
535 }
536 }
537
538 // Back substitution
539 Mat x(b.rows, 1);
540 x((x.rows - 1), 0) = b((x.rows - 1), 0) / A((x.rows - 1), (x.rows - 1));
541 for (int i = x.rows - 2; i >= 0; --i) {
542 float sum = 0;
543 for (int j = i + 1; j < x.rows; ++j) {
544 sum += A(i, j) * x(j, 0);
545 }
546 x(i, 0) = (b(i, 0) - sum) / A(i, i);
547 }
548
549 return x;
550}
551
553{
554 int n = A.cols + 1;
555
556 Mat result(y.rows, 1);
557
558 Mat g_m = Mat::augment(A, y);
559 for (int j = 0; j < A.cols; j++) {
560 float g_jj = 1 / g_m(j, j);
561 for (int i = 0; i < A.cols; i++) {
562 if (i != j) {
563 float c = g_m(i, j) * g_jj;
564 for (int k = 0; k < n; k++) {
565 g_m(i, k) = g_m(i, k) - c * g_m(j, k);
566 }
567 }
568 }
569 }
570 for (int i = 0; i < A.rows; i++) {
571 result(i, 0) = g_m(i, A.cols) / g_m(i, i);
572 }
573 return result;
574}
575
577{
578 float sum = 0;
579 for (int i = 0; i < a.rows; ++i) {
580 sum += (a(i, 0) * b(i, 0));
581 }
582 return sum;
583}
584
586{
587 Mat AB(A.rows, A.cols + B.cols);
588 for (int i = 0; i < AB.rows; ++i) {
589 for (int j = 0; j < AB.cols; ++j) {
590 if (j < A.cols) {
591 AB(i, j) = A(i, j);
592 } else {
593 AB(i, j) = B(i, j - A.cols);
594 }
595 }
596 }
597 return AB;
598}
599
601{
602 Mat Ab(*this);
603 int rows = Ab.rows;
604 int cols = Ab.cols;
605 int Acols = cols - 1;
606
607 int i = 0; // row tracker
608 int j = 0; // column tracker
609
610 // iterate through the rows
611 while (i < rows) {
612 // find a pivot for the row
613 bool pivot_found = false;
614 while (j < Acols && !pivot_found) {
615 if (Ab(i, j) != 0) { // pivot not equal to 0
616 pivot_found = true;
617 } else { // check for a possible swap
618 int max_row = i;
619 float max_val = 0;
620 for (int k = i + 1; k < rows; ++k) {
621 float cur_abs = Ab(k, j) >= 0 ? Ab(k, j) : -1 * Ab(k, j);
622 if (cur_abs > max_val) {
623 max_row = k;
624 max_val = cur_abs;
625 }
626 }
627 if (max_row != i) {
628 Ab.swapRows(max_row, i);
629 pivot_found = true;
630 } else {
631 j++;
632 }
633 }
634 }
635
636 // perform elimination as normal if pivot was found
637 if (pivot_found) {
638 for (int t = i + 1; t < rows; ++t) {
639 for (int s = j + 1; s < cols; ++s) {
640 Ab(t, s) = Ab(t, s) - Ab(i, s) * (Ab(t, j) / Ab(i, j));
641 if (Ab(t, s) < abs_tol && Ab(t, s) > -1 * abs_tol) {
642 Ab(t, s) = 0;
643 }
644 }
645 Ab(t, j) = 0;
646 }
647 }
648
649 i++;
650 j++;
651 }
652
653 return Ab;
654}
655
657{
658 Mat R(*this);
659 int rows = R.rows;
660 int cols = R.cols;
661
662 int i = rows - 1; // row tracker
663 int j = cols - 2; // column tracker
664
665 // iterate through every row
666 while (i >= 0) {
667 // find the pivot column
668 int k = j - 1;
669 while (k >= 0) {
670 if (R(i, k) != 0) {
671 j = k;
672 }
673 k--;
674 }
675
676 // zero out elements above pivots if pivot not 0
677 if (R(i, j) != 0) {
678 for (int t = i - 1; t >= 0; --t) {
679 for (int s = 0; s < cols; ++s) {
680 if (s != j) {
681 R(t, s) = R(t, s) - R(i, s) * (R(t, j) / R(i, j));
682 if (R(t, s) < abs_tol && R(t, s) > -1 * abs_tol) {
683 R(t, s) = 0;
684 }
685 }
686 }
687 R(t, j) = 0;
688 }
689
690 // divide row by pivot
691 for (int k = j + 1; k < cols; ++k) {
692 R(i, k) = R(i, k) / R(i, j);
693 if (R(i, k) < abs_tol && R(i, k) > -1 * abs_tol) {
694 R(i, k) = 0;
695 }
696 }
697 R(i, j) = 1;
698 }
699
700 i--;
701 j--;
702 }
703
704 return R;
705}
706
708{
709 Mat I = Mat::eye(this->rows);
710 Mat AI = Mat::augment(*this, I);
711 Mat U = AI.gaussianEliminate();
712 Mat IAInverse = U.rowReduceFromGaussian();
713 Mat AInverse(this->rows, this->cols);
714 for (int i = 0; i < this->rows; ++i) {
715 for (int j = 0; j < this->cols; ++j) {
716 AInverse(i, j) = IAInverse(i, j + this->cols);
717 }
718 }
719 return AInverse;
720}
721
722Mat Mat::cofactor(int row, int col, int n)
723{
724 int i = 0, j = 0;
725 Mat result(n, n);
726 // Looping for each element of the matrix
727 for (int r = 0; r < n; r++) {
728 for (int c = 0; c < n; c++) {
729 // Copying into temporary matrix only those element
730 // which are not in given row and column
731 if (r != row && c != col) {
732 result(i, j++) = (*this)(r, c);
733
734 // Row is filled, so increase row index and
735 // reset col index
736 if (j == this->rows - 1) {
737 j = 0;
738 i++;
739 }
740 }
741 }
742 }
743 return result;
744}
745
746float Mat::det(int n)
747{
748 // Base case : if matrix contains single element
749 if (n == 1) {
750 return (*this)(0, 0);
751 }
752
753 float det = 1.0;
754 Mat *temp = new Mat(n, n);
755 *temp = *this;
756
757 for (int i = 0; i < n; i++) {
758 int pivot = i;
759 for (int j = i + 1; j < n; j++) {
760 if (std::abs((*temp)(j, i)) > std::abs((*temp)(pivot, i))) {
761 pivot = j;
762 }
763 }
764 if (pivot != i) {
765 temp->swapRows(i, pivot);
766 det *= -1;
767 }
768 if ((*temp)(i, i) == 0) {
769 return 0;
770 }
771 det *= (*temp)(i, i);
772 for (int j = i + 1; j < n; j++) {
773 float factor = (*temp)(j, i) / (*temp)(i, i);
774 for (int k = i + 1; k < n; k++) {
775 (*temp)(j, k) -= factor * (*temp)(i, k);
776 }
777 }
778 }
779 delete temp;
780 return det;
781}
782
784{
785 Mat adj(this->rows, this->cols);
786 if (this->rows == 1) {
787 adj(0, 0) = 1;
788 return adj;
789 }
790
791 // temp is used to store cofactors of A(,)
792 int sign = 1;
793 Mat temp(this->rows, this->cols);
794
795 for (int i = 0; i < this->rows; i++) {
796 for (int j = 0; j < this->cols; j++) {
797 // Get cofactor of A(i,j)
798 temp = this->cofactor( i, j, this->rows);
799
800 // sign of adj(j,i) positive if sum of row
801 // and column indexes is even.
802 sign = ((i + j) % 2 == 0) ? 1 : -1;
803
804 // Interchanging rows and columns to get the
805 // transpose of the cofactor matrix
806 adj(j, i) = (sign) * (temp.det(this->rows - 1));
807 }
808 }
809 return adj;
810}
811
813{
814 Mat result(this->rows, this->cols);
815 // Find determinant of matrix
816 float det = this->det(this->rows);
817 if (det == 0) {
818 //std::cout << "Singular matrix, can't find its inverse";
819 return result;
820 }
821
822 // Find adjoint
823 Mat adj = this->adjoint();
824
825 // Find Inverse using formula "inverse(A) = adj(A)/det(A)"
826 for (int i = 0; i < this->rows; i++)
827 for (int j = 0; j < this->cols; j++) {
828 result(i, j) = adj(i, j) / float(det);
829 }
830
831 return result;
832}
833
835{
836 this->ext_buff = false;
837 this->length = this->rows * this->cols;
838 data = new float[this->length];
839 ESP_LOGD("Mat", "allocate(%i) = %p", this->length, this->data);
840}
841
842Mat Mat::expHelper(const Mat &m, int num)
843{
844 if (num == 0) {
845 return Mat::eye(m.rows);
846 } else if (num == 1) {
847 return m;
848 } else if (num % 2 == 0) { // num is even
849 return expHelper(m * m, num / 2);
850 } else { // num is odd
851 return m * expHelper(m * m, (num - 1) / 2);
852 }
853}
854
855Mat operator+(const Mat &m1, const Mat &m2)
856{
857 if ((m1.rows != m2.rows) || (m1.cols != m2.cols)) {
858 ESP_LOGW("Mat", "operator + Error: matrices do not have equal dimensions");
859 Mat err_ret;
860 return err_ret;
861 }
862
863 if (m1.sub_matrix || m2.sub_matrix) {
864 Mat temp(m1.rows, m2.cols);
865 dspm_add_f32(m1.data, m2.data, temp.data, m1.rows, m1.cols, m1.padding, m2.padding, temp.padding, 1, 1, 1);
866 return temp;
867 } else {
868 Mat temp(m1);
869 return (temp += m2);
870 }
871}
872
873Mat operator+(const Mat &m, float C)
874{
875 if (m.sub_matrix) {
876 Mat temp(m.rows, m.cols);
877 dspm_addc_f32(m.data, temp.data, C, m.rows, m.cols, m.padding, temp.padding, 1, 1);
878 return temp;
879 } else {
880 Mat temp(m);
881 return (temp += C);
882 }
883}
884
885bool operator==(const Mat &m1, const Mat &m2)
886{
887 if ((m1.cols != m2.cols) || (m1.rows != m2.rows)) {
888 return false;
889 }
890
891 for (int row = 0; row < m1.rows; row++) {
892 for (int col = 0; col < m1.cols; col++) {
893 if (m1(row, col) != m2(row, col)) {
894 ESP_LOGW("Mat", "operator == Error: %i %i, m1.data=%f, m2.data=%f \n", row, col, m1(row, col), m2(row, col));
895 return false;
896 }
897 }
898 }
899
900 return true;
901}
902
903Mat operator-(const Mat &m1, const Mat &m2)
904{
905 if ((m1.rows != m2.rows) || (m1.cols != m2.cols)) {
906 ESP_LOGW("Mat", "operator - Error: matrices do not have equal dimensions");
907 Mat err_ret;
908 return err_ret;
909 }
910
911 if (m1.sub_matrix || m2.sub_matrix) {
912 Mat temp(m1.rows, m1.cols);
913 dspm_sub_f32(m1.data, m2.data, temp.data, m1.rows, m1.cols, m1.padding, m2.padding, temp.padding, 1, 1, 1);
914 return temp;
915 } else {
916 Mat temp(m1);
917 return (temp -= m2);
918 }
919}
920
921Mat operator-(const Mat &m, float C)
922{
923 if (m.sub_matrix) {
924 Mat temp(m.rows, m.cols);
925 dspm_addc_f32(m.data, temp.data, -C, m.rows, m.cols, m.padding, temp.padding, 1, 1);
926 return temp;
927 } else {
928 Mat temp(m);
929 return (temp -= C);
930 }
931}
932
933Mat operator*(const Mat &m1, const Mat &m2)
934{
935 if (m1.cols != m2.rows) {
936 ESP_LOGW("Mat", "operator * Error: matrices do not have correct dimensions");
937 Mat err_ret;
938 return err_ret;
939 }
940 Mat temp(m1.rows, m2.cols);
941
942 if (m1.sub_matrix || m2.sub_matrix) {
943 dspm_mult_ex_f32(m1.data, m2.data, temp.data, m1.rows, m1.cols, m2.cols, m1.padding, m2.padding, temp.padding);
944 } else {
945 dspm_mult_f32(m1.data, m2.data, temp.data, m1.rows, m1.cols, m2.cols);
946 }
947
948 return temp;
949
950}
951
952Mat operator*(const Mat &m, float num)
953{
954 if (m.sub_matrix) {
955 Mat temp(m.rows, m.cols);
956 dspm_mulc_f32(m.data, temp.data, num, m.rows, m.cols, m.padding, temp.padding, 1, 1);
957 return temp;
958 } else {
959 Mat temp(m);
960 return (temp *= num);
961 }
962}
963
964Mat operator*(float num, const Mat &m)
965{
966 return (m * num);
967}
968
969Mat operator/(const Mat &m, float num)
970{
971 if (m.sub_matrix) {
972 Mat temp(m.rows, m.cols);
973 dspm_mulc_f32(m.data, temp.data, 1 / num, m.rows, m.cols, m.padding, temp.padding, 1, 1);
974 return temp;
975 } else {
976 Mat temp(m);
977 return (temp /= num);
978 }
979}
980
981Mat operator/(const Mat &A, const Mat &B)
982{
983 if ((A.rows != B.rows) || (A.cols != B.cols)) {
984 ESP_LOGW("Mat", "Operator + Error: matrices do not have equal dimensions");
985 Mat err_ret;
986 return err_ret;
987 }
988
989 Mat temp(A.rows, A.cols);
990 for (int row = 0; row < A.rows; row++) {
991 for (int col = 0; col < A.cols; col++) {
992 temp(row, col) = A(row, col) / B(row, col);
993 }
994 }
995 return temp;
996}
997
998ostream &operator<<(ostream &os, const Mat &m)
999{
1000 for (int i = 0; i < m.rows; ++i) {
1001 os << m(i, 0);
1002 for (int j = 1; j < m.cols; ++j) {
1003 os << " " << m(i, j);
1004 }
1005 os << endl;
1006 }
1007 return os;
1008}
1009
1010ostream &operator<<(ostream &os, const Mat::Rect &rect)
1011{
1012 os << "row start " << rect.y << endl;
1013 os << "col start " << rect.x << endl;
1014 os << "row count " << rect.height << endl;
1015 os << "col count " << rect.width << endl;
1016
1017 return os;
1018}
1019
1020istream &operator>>(istream &is, Mat &m)
1021{
1022 for (int i = 0; i < m.rows; ++i) {
1023 for (int j = 0; j < m.cols; ++j) {
1024 is >> m(i, j);
1025 }
1026 }
1027 return is;
1028}
1029
1030}
Matrix.
Definition mat.h:30
Mat Get(int row_start, int row_size, int col_start, int col_size)
Definition mat.cpp:209
Mat & operator+=(const Mat &A)
Definition mat.cpp:262
float det(int n)
Definition mat.cpp:746
static float abs_tol
Definition mat.h:39
Mat operator^(int C)
Definition mat.cpp:364
Mat rowReduceFromGaussian()
Definition mat.cpp:656
static Mat ones(int size)
Definition mat.cpp:409
void PrintHead(void)
print matrix header
Definition mat.cpp:197
int stride
Definition mat.h:35
Mat adjoint()
Definition mat.cpp:783
float * data
Definition mat.h:37
void normalize(void)
Definition mat.cpp:444
float norm(void)
Definition mat.cpp:456
Mat pinv()
Definition mat.cpp:707
Mat()
Definition mat.cpp:98
static float dotProduct(Mat A, Mat B)
Dotproduct of two vectors.
Definition mat.cpp:576
int cols
Definition mat.h:34
Mat(int rows, int cols)
Definition mat.cpp:69
bool ext_buff
Definition mat.h:40
void clear(void)
Definition mat.cpp:425
Mat & operator=(const Mat &src)
Definition mat.cpp:231
Mat & operator*=(const Mat &A)
Definition mat.cpp:312
int length
Definition mat.h:38
static Mat eye(int size)
Definition mat.cpp:394
Mat expHelper(const Mat &m, int num)
Definition mat.cpp:842
Mat block(int startRow, int startCol, int blockRows, int blockCols)
Definition mat.cpp:433
virtual ~Mat()
Definition mat.cpp:111
static Mat bandSolve(Mat A, Mat b, int k)
Band solve the matrix.
Definition mat.cpp:514
bool sub_matrix
Definition mat.h:41
int padding
Definition mat.h:36
void Copy(const Mat &src, int row_pos, int col_pos)
Definition mat.cpp:168
void swapRows(int row1, int row2)
Definition mat.cpp:370
void CopyHead(const Mat &src)
copy header of matrix
Definition mat.cpp:182
Mat getROI(int startRow, int startCol, int roiRows, int roiCols)
Create a subset of matrix as ROI (Region of Interest).
Definition mat.cpp:163
void allocate()
Definition mat.cpp:834
int rows
Definition mat.h:33
Mat & operator/=(float C)
Definition mat.cpp:354
Mat gaussianEliminate()
Gaussian Elimination.
Definition mat.cpp:600
static Mat augment(Mat A, Mat B)
Augmented matrices.
Definition mat.cpp:585
static Mat solve(Mat A, Mat b)
Solve the matrix.
Definition mat.cpp:468
Mat cofactor(int row, int col, int n)
Definition mat.cpp:722
Mat t()
Definition mat.cpp:383
static Mat roots(Mat A, Mat y)
Solve the matrix.
Definition mat.cpp:552
Mat inverse()
Definition mat.cpp:812
Mat & operator-=(const Mat &A)
Definition mat.cpp:287
#define dspm_add_f32
Definition dspm_add.h:62
#define dspm_addc_f32
Definition dspm_addc.h:57
#define dspm_mulc_f32
Definition dspm_mulc.h:57
#define dspm_mult_ex_f32
Definition dspm_mult.h:226
#define dspm_mult_f32
Definition dspm_mult.h:221
#define dspm_sub_f32
Definition dspm_sub.h:58
#define dsps_add_f32
Definition dsps_add.h:84
esp_err_t dsps_addc_f32_ansi(const float *input, float *output, int len, float C, int step_in, int step_out)
add constant
esp_err_t dsps_mulc_f32_ansi(const float *input, float *output, int len, float C, int step_in, int step_out)
multiply constant
#define dsps_sub_f32
Definition dsps_sub.h:82
#define ESP_LOGD
Definition esp_log.h:22
DSP matrix namespace.
Definition mat.h:24
std::istream & operator>>(std::istream &is, Mat &m)
std::ostream & operator<<(std::ostream &os, const Mat &m)
Mat operator-(const Mat &A, const Mat &B)
Definition mat.cpp:903
Mat operator+(const Mat &A, const Mat &B)
Definition mat.cpp:855
bool operator==(const Mat &A, const Mat &B)
Definition mat.cpp:885
Mat operator/(const Mat &A, float C)
Definition mat.cpp:969
Mat operator*(const Mat &A, const Mat &B)
Definition mat.cpp:933
Rectangular area.
Definition mat.h:48
int width
Definition mat.h:51
int height
Definition mat.h:52
void resizeRect(int x, int y, int width, int height)
Resize rect area.
Definition mat.cpp:44
Rect(int x=0, int y=0, int width=0, int height=0)
Constructor with initialization to 0.
Definition mat.cpp:36
int areaRect(void)
Get amount of elements in the rect area.
Definition mat.cpp:52
float y[1024]
Definition test_fir.c:11
float x[1024]
Definition test_fir.c:10
float C[4][16]
Definition test_mmult.c:22
const int m
Definition test_mmult.c:16
float B[8][16]
Definition test_mmult.c:21
float A[4][8]
Definition test_mmult.c:20
const int n
Definition test_mmult.c:17
const int k
Definition test_mmult.c:18