Files
snapclient/components/esp-dsp/modules/matrix/test/test_mat_f32.cpp
Carlos 15b4baba28 - merge with original master from jorgen
- minimize RAM usage of all components
- use both IRAM and DRAM in player component so we can buffer up to 1s on modules without SPI RAM
- support fragemented pcm chunks so we can use all available RAM if there isn't a big enough block available but still enough HEAP
- reinclude all components from jorgen's master branch
- add custom i2s driver to get a precise timing of initial sync
- change wrong usage of esp_timer for latency measurement of snapcast protocol
- add player component
2021-08-19 21:57:16 +02:00

280 lines
8.0 KiB
C++

// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "unity.h"
#include "dsp_platform.h"
#include "esp_log.h"
#include "dspm_mult.h"
#include "esp_attr.h"
#include "dsp_tests.h"
#include "mat.h"
static const char *TAG = "dspm_Mat";
TEST_CASE("Mat class ", "[dspm]")
{
int m = 3;
int n = 3;
dspm::Mat mat(m, n);
std::cout << "Test matrix: rows: " << mat.rows << ", columns: " << mat.cols << std::endl;
std::cout << mat;
}
TEST_CASE("Mat class check solve ", "[dspm]")
{
int m = 3;
int n = 3;
float data_a[9] ={3, 2, 1, 2, 3, 1, 2, 1, 3};
float data_b[9] ={5, -1, 4};
dspm::Mat A(data_a, m, n);
dspm::Mat b(data_b, m, 1);
dspm::Mat x1 = dspm::Mat::solve(A, b);
std::cout << "Solve result matrix: rows: " << x1.rows << ", columns: " << x1.cols << std::endl;
std::cout << (x1*12).t();
dspm::Mat x2 = dspm::Mat::roots(A, b);
std::cout << "Roots result matrix: rows: " << x2.rows << ", columns: " << x2.cols << std::endl;
std::cout << (x2*12).t();
dspm::Mat diff_b = x1 - x2;
std::cout << "Difference between solve() abd roots(): " << diff_b.t();
for (int m=0 ; m < diff_b.rows; m++)
{
for (int n=0 ; n < diff_b.cols ; n++)
{
if (fabs(diff_b(m, n)) > 0.000001)
{
TEST_ASSERT_MESSAGE (false, "Calculation is incorrect! Error more then expected!");
}
}
}
}
TEST_CASE("Mat class basic operations", "[dspm]")
{
int M = 4;
int N = 4;
dspm::Mat A(M, N);
dspm::Mat x(N, 1);
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
A(m,n) = N*(m + 1) + (n + 1);
}
x(m, 0) = m + 2;
}
A(0,0) = 10;
A(0,1) = 11;
dspm::Mat b = A*x;
dspm::Mat x1_ = dspm::Mat::solve(A, b);
dspm::Mat x2_ = dspm::Mat::roots(A, b);
ESP_LOGI(TAG, "Matrix A:");
std::cout << A;
ESP_LOGI(TAG, "Matrix x.t():");
std::cout << x.t();
ESP_LOGI(TAG, "Matrix b.t():");
std::cout << b.t();
ESP_LOGI(TAG, "Solve result:");
std::cout << x1_.t();
ESP_LOGI(TAG, "Roots result:");
std::cout << x2_.t();
dspm::Mat check_b = A*x1_;
ESP_LOGI(TAG, "Result b.t():");
std::cout << check_b.t();
dspm::Mat diff_b = check_b - b;
ESP_LOGI(TAG, "Difference:");
std::cout << diff_b.t();
for (int m=0 ; m < diff_b.rows; m++)
{
for (int n=0 ; n < diff_b.cols ; n++)
{
float error = fabs(diff_b(m, n));
if (fabs(diff_b(m, n)) > 0.0001)
{
ESP_LOGE(TAG,"Solve calculation error: %f", error);
TEST_ASSERT_MESSAGE (false, "Calculation is incorrect! Error more then expected!");
}
}
}
}
TEST_CASE("Mat class operators", "[dspm]")
{
int M = 4;
int N = 4;
dspm::Mat test1(M, N);
dspm::Mat test2(M, N);
dspm::Mat result(M, N);
float* check_array = new float[M*N];
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n< N ; n++)
{
test1(m,n) = m*N + n;
test2(m,n) = m*N + n;
result(m,n) = 0;
}
}
result = test1 + test2;
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
if ((result(m,n) != 2*test1(m,n)) ||
(result(m,n) != 2*(m*N + n)) ||
(result.data[m*N + n] != 2*(m*N + n)))
{
TEST_ASSERT_MESSAGE (false, "Error in + operator!");
}
}
}
result = test1 - test2;
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
if ((result(m,n) != (test1(m,n) - test2(m,n))) ||
(result(m,n) != 0) ||
(result.data[m*N + n] != 0))
{
TEST_ASSERT_MESSAGE (false, "Error in - operator!");
}
}
}
// Check * operator (result = A*B;)
// result = I*test2
// result == test2
test1 = test1.eye(test1.rows);
result = test1 * test2;
dspm::Mat result2 = test1;
result2 *= test2;
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
if ((result(m,n) != test2(m,n)) ||
(result(m,n) != (m*N + n)) ||
(result.data[m*N + n] != (m*N + n)))
{
TEST_ASSERT_MESSAGE (false, "Error in * operator!");
}
}
}
if (!(result == result2))
{
std::cout << "result matrix: " << std::endl << result << std::endl;
std::cout << "result2 matrix: " << std::endl << result2 << std::endl;
TEST_ASSERT_MESSAGE (false, "Error in *= or in == operator!");
}
// Check * and + operator (result = A*const1 + const2;)
test1 = test2;
float const1 = 2;
float const2 = 10;
result = test1*const1 + const2;
result = (result - const2)/const1;
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
if ((result(m,n) != test2(m,n)) ||
(result(m,n) != (m*N + n)) ||
(result.data[m*N + n] != (m*N + n))
)
{
TEST_ASSERT_MESSAGE (false, "Error in + * const operator!");
}
}
}
// Test block(...):
int count = 0;
for (int m=0 ; m < M ; m++)
{
for (int n=0 ; n < N ; n++)
{
result(m,n) = count++;
}
}
std::cout << "Original matrix: " << std::endl;
std::cout << result << std::endl;
std::cout << "block: " << std::endl;
std::cout << result.block(1,1,M-1, N-1) << std::endl;
// Test normalize()
result = dspm::Mat(2,2);
for (int m=0 ; m < result.rows ; m++)
{
for (int n=0 ; n < result.cols ; n++)
{
result(m,n) = 1;
}
}
result.normalize();
std::cout << "normalize: " << std::endl;
std::cout << result << std::endl;
for (int m=0 ; m < result.rows ; m++)
{
for (int n=0 ; n < result.cols ; n++)
{
if (std::abs(result(m,n) - 0.5) > dspm::Mat::abs_tol)
{
TEST_ASSERT_MESSAGE (false, "Error in normalize() operation!");
}
}
}
// Test inverse()
float m_data[] = {2,5,7,
6,3,4,
5,-2,-3};
float m_result[] = { 1.0000, -1.0000, 1.0000,
-38.0000, 41.0000, -34.0000,
27.0000, -29.0000, 24.0000};
result = dspm::Mat(m_data, 3,3);
result = result.inverse();
std::cout << "inverse: " << std::endl;
std::cout << result << std::endl;
for (int i=0 ; i< 3*3 ; i++)
{
if (std::abs(result.data[i] - m_result[i]) > 1e-8)
{
printf("Error at[%i] = %f, expected= %f, calculated = %f \n", i, std::abs(result.data[i] - m_result[i]), m_result[i], result.data[i]);
TEST_ASSERT_MESSAGE (false, "Error in inverse() operation!\n");
}
}
result = dspm::Mat(m_data, 3,3);
result = result.pinv();
std::cout << "pinv: " << std::endl;
std::cout << result << std::endl;
for (int i=0 ; i< 3*3 ; i++)
{
if (std::abs(result.data[i] - m_result[i]) > 1e-2)
{
printf("Error at[%i] = %f, expected= %f, calculated = %f \n", i, std::abs(result.data[i] - m_result[i]), m_result[i], result.data[i]);
TEST_ASSERT_MESSAGE (false, "Error in pinv() operation!\n");
}
}
delete check_array;
}