From 9c40473a9668b60ef4a4d75485b34ef9cda5f89f Mon Sep 17 00:00:00 2001 From: Shubham Sharma Date: Mon, 11 Mar 2024 14:36:17 +0530 Subject: [PATCH] GTestSuite: Added Tests for DTRSV - Added API tests for DTRSV. - Added Extreme Value Test cases (EVT) for DTRSV. - Tests for various combinations of INFs and NANs for X vector and B matrix are added. - Added Invalid input test cases (IIT). - Added memory testing for DTRSV kernels. - Fixed a bug in alphax function where scaling of a vector with a scalar was not handled correctly when incx was negative. AMD-Internal: [CPUPL-4715] Change-Id: I84c873e98f845e05b11860e7ef6083d1184489b4 --- .../inc/common/testing_basics.h | 6 +- .../testsuite/level2/trsv/IIT_ERS_test.cpp | 190 ++++++++++++++++++ .../level2/trsv/dtrsv_evt_testing.cpp | 171 ++++++++++++++++ .../testsuite/level2/trsv/dtrsv_generic.cpp | 112 ++++++----- gtestsuite/testsuite/level2/trsv/test_trsv.h | 96 ++++++++- 5 files changed, 516 insertions(+), 59 deletions(-) create mode 100644 gtestsuite/testsuite/level2/trsv/IIT_ERS_test.cpp create mode 100644 gtestsuite/testsuite/level2/trsv/dtrsv_evt_testing.cpp diff --git a/gtestsuite/testinghelpers/inc/common/testing_basics.h b/gtestsuite/testinghelpers/inc/common/testing_basics.h index 97d7b000e..ee3dadb72 100644 --- a/gtestsuite/testinghelpers/inc/common/testing_basics.h +++ b/gtestsuite/testinghelpers/inc/common/testing_basics.h @@ -4,7 +4,7 @@ An object-based framework for developing high-performance BLAS-like libraries. - Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. + Copyright (C) 2023-2024, Advanced Micro Devices, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -173,7 +173,9 @@ static void alphax( gtint_t n, T alpha, T *xp, gtint_t incx ) gtint_t ix = 0; for(i = 0 ; i < n ; i++) { xp[ix] = (alpha * xp[ix]); - ix = ix + incx; + // use absolute value of incx to ensure + // correctness when incx < 0 + ix = ix + std::abs(incx); } } diff --git a/gtestsuite/testsuite/level2/trsv/IIT_ERS_test.cpp b/gtestsuite/testsuite/level2/trsv/IIT_ERS_test.cpp new file mode 100644 index 000000000..8aca8ba00 --- /dev/null +++ b/gtestsuite/testsuite/level2/trsv/IIT_ERS_test.cpp @@ -0,0 +1,190 @@ +/* + + BLIS + An object-based framework for developing high-performance BLAS-like + libraries. + + Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name(s) of the copyright holder(s) nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "trsv.h" +#include "inc/check_error.h" +#include "common/testing_helpers.h" +#include "common/wrong_inputs_helpers.h" +#include +#include +#include + +template +class TRSV_IIT_ERS_Test : public ::testing::Test {}; +typedef ::testing::Types TypeParam; +TYPED_TEST_SUITE(TRSV_IIT_ERS_Test, TypeParam); + + +#ifdef TEST_BLAS + +using namespace testinghelpers::IIT; + +/* + Incorrect Input Testing(IIT) + + BLAS exceptions get triggered in the following cases(for TRSV): + 1. When UPLO != 'L' || UPLO != 'U' (info = 1) + 2. When TRANS != 'N' || TRANS != 'T' || TRANS != 'C' (info = 2) + 3. When DIAG != 'U' || DIAG != 'N' (info = 3) + 4. When n < 0 (info = 4) + 5. When lda < N (info = 6) + 6. When incx == 0 (info = 8) +*/ + + +/** + * @brief Test TRSV when UPLO argument is incorrect + * when info == 1 + * + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_UPLO) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, 'A', TRANS, DIAG, N, &alpha, nullptr, LDA, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + +/** + * @brief Test TRSV when TRANS argument is incorrect + * when info == 2 + * + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_TRANS) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, 'A', DIAG, N, &alpha, nullptr, LDA, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + +/** + * @brief Test TRSV when DIAG argument is incorrect + * when info == 3 + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_DIAG) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, TRANS, 'A', N, &alpha, nullptr, LDA, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + +/** + * @brief Test TRSV when N is negative + * when info == 4 + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_n) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, TRANS, DIAG, -1, &alpha, nullptr, LDA, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + + +/** + * @brief Test TRSV when lda < max(1, N) + * when info == 6 + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_lda) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, TRANS, DIAG, N, &alpha, nullptr, LDA - 1, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + +/** + * @brief Test TRSV when INCX == 0 + * when info == 8 + */ +TYPED_TEST(TRSV_IIT_ERS_Test, invalid_incx) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, TRANS, DIAG, N, &alpha, nullptr, LDA, x.data(), 0); + computediff( N, x.data(), x_ref.data(), INC ); +} + + +/* + Early Return Scenarios(ERS) : + + The TRSV API is expected to return early in the following cases: + + 1. When n == 0. + +*/ + +/** + * @brief Test TRSV when N is zero + */ +TYPED_TEST(TRSV_IIT_ERS_Test, n_eq_zero) +{ + using T = TypeParam; + T alpha = T{1}; + + std::vector x = testinghelpers::get_random_vector(0, 1, N, INC); + std::vector x_ref(x); + + trsv( STORAGE, UPLO, TRANS, DIAG, 0, &alpha, nullptr, LDA, x.data(), INC); + computediff( N, x.data(), x_ref.data(), INC ); +} + +#endif \ No newline at end of file diff --git a/gtestsuite/testsuite/level2/trsv/dtrsv_evt_testing.cpp b/gtestsuite/testsuite/level2/trsv/dtrsv_evt_testing.cpp new file mode 100644 index 000000000..ba8665b6a --- /dev/null +++ b/gtestsuite/testsuite/level2/trsv/dtrsv_evt_testing.cpp @@ -0,0 +1,171 @@ +/* + + BLIS + An object-based framework for developing high-performance BLAS-like + libraries. + + Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name(s) of the copyright holder(s) nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include "test_trsv.h" + +class dtrsvEVT : + public ::testing::TestWithParam> {}; // ld_inc + +TEST_P( dtrsvEVT, NaNInfCheck ) +{ + using T = double; + //---------------------------------------------------------- + // Initialize values from the parameters passed through + // test suite instantiation (INSTANTIATE_TEST_SUITE_P). + //---------------------------------------------------------- + // matrix storage format(row major, column major) + char storage = std::get<0>(GetParam()); + // denotes whether matrix a is u,l + char uploa = std::get<1>(GetParam()); + // denotes whether matrix a is n,c,t,h + char transa = std::get<2>(GetParam()); + // denotes whether matrix diag is u,n + char diaga = std::get<3>(GetParam()); + // matrix size n + gtint_t n = std::get<4>(GetParam()); + // specifies alpha value + T alpha = std::get<5>(GetParam()); + // stride size for x: + gtint_t incx = std::get<6>(GetParam()); + // extreme value for x + double xexval = std::get<7>(GetParam()); + // extreme value for A + double aexval = std::get<8>(GetParam()); + // lda increment. + // If increment is zero, then the array size matches the matrix size. + // If increment are nonnegative, the array size is bigger than the matrix size. + gtint_t lda_inc = std::get<9>(GetParam()); + + // Set the threshold for the errors: + // Check gtestsuite trsv.h or netlib source code for reminder of the + // functionality from which we estimate operation count per element + // of output, and hence the multipler for epsilon. + double thresh; + if (n == 0) + thresh = 0.0; + else + thresh = 2*n*testinghelpers::getEpsilon(); + + //---------------------------------------------------------- + // Call test body using these parameters + //---------------------------------------------------------- + test_trsv( storage, uploa, transa, diaga, n, alpha, lda_inc, incx, thresh, false, true, xexval, aexval); +} + +class dtrsvEVTPrint +{ +public: + std::string operator()( + testing::TestParamInfo> str) const { + char sfm = std::get<0>(str.param); + char uploa = std::get<1>(str.param); + char transa = std::get<2>(str.param); + char diaga = std::get<3>(str.param); + gtint_t n = std::get<4>(str.param); + double alpha = std::get<5>(str.param); + gtint_t incx = std::get<6>(str.param); + double xexval = std::get<7>(str.param); + double aexval = std::get<8>(str.param); + gtint_t ld_inc = std::get<9>(str.param); +#ifdef TEST_BLAS + std::string str_name = "blas_"; +#elif TEST_CBLAS + std::string str_name = "cblas_"; +#else //#elif TEST_BLIS_TYPED + std::string str_name = "bli_"; +#endif + str_name = str_name + "stor_" + sfm; + str_name = str_name + "_uplo_" + uploa; + str_name = str_name + "_transa_" + transa; + str_name = str_name + "_diaga_" + diaga; + str_name = str_name + "_n_" + std::to_string(n); + std::string alpha_str = testinghelpers::get_value_string(alpha); + str_name = str_name + "_alpha_" + alpha_str; + std::string incx_str = ( incx > 0) ? std::to_string(incx) : "m" + std::to_string(std::abs(incx)); + str_name = str_name + "_incx_" + incx_str; + str_name = str_name + "_ex_x_" + testinghelpers::get_value_string(xexval); + str_name = str_name + "_ex_a_" + testinghelpers::get_value_string(aexval); + str_name = str_name + "_lda_" + std::to_string( + testinghelpers::get_leading_dimension( sfm, transa, n, n, ld_inc ) + ); + return str_name; + } +}; + +static double AOCL_NAN = std::numeric_limits::quiet_NaN(); +static double AOCL_INF = std::numeric_limits::infinity(); + +INSTANTIATE_TEST_SUITE_P( + Native, + dtrsvEVT, + ::testing::Combine( + ::testing::Values('c' +#ifndef TEST_BLAS + ,'r' +#endif + ), // storage format + ::testing::Values('u','l'), // uploa + ::testing::Values('n','t'), // transa + ::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG + ::testing::Values(gtint_t(32), + gtint_t(24), + gtint_t(8), + gtint_t(4), + gtint_t(2), + gtint_t(1), + gtint_t(15) + ), // n (random values) + ::testing::Values( 1.0 +#ifdef TEST_BLIS_TYPED + , -2.2, 5.4, -1.0, 0.0 +#endif + ), // alpha + ::testing::Values(gtint_t(-2), gtint_t(-1), + gtint_t( 1), gtint_t( 2)), // stride size for x + ::testing::Values(AOCL_NAN, -AOCL_INF, AOCL_INF, 1 /*,0 <-fail*/),// exception value for x + ::testing::Values(AOCL_NAN, -AOCL_INF, AOCL_INF 0), // exception value for A + ::testing::Values(gtint_t(0), gtint_t(10)) // increment to the leading dim of a + ), + ::dtrsvEVTPrint() + ); diff --git a/gtestsuite/testsuite/level2/trsv/dtrsv_generic.cpp b/gtestsuite/testsuite/level2/trsv/dtrsv_generic.cpp index 86aaf44d4..f133ec927 100644 --- a/gtestsuite/testsuite/level2/trsv/dtrsv_generic.cpp +++ b/gtestsuite/testsuite/level2/trsv/dtrsv_generic.cpp @@ -35,17 +35,18 @@ #include #include "test_trsv.h" -class dtrsvTest : - public ::testing::TestWithParam> {}; +class dtrsvAPI : + public ::testing::TestWithParam> {}; // is memory test -TEST_P(dtrsvTest, RandomData) +TEST_P(dtrsvAPI, FunctionalTest) { using T = double; //---------------------------------------------------------- @@ -54,9 +55,9 @@ TEST_P(dtrsvTest, RandomData) //---------------------------------------------------------- // matrix storage format(row major, column major) char storage = std::get<0>(GetParam()); - // denotes whether matrix a is u,l + // denotes whether matrix A is u,l char uploa = std::get<1>(GetParam()); - // denotes whether matrix a is n,c,t,h + // denotes whether matrix A is n,c,t,h char transa = std::get<2>(GetParam()); // denotes whether matrix diag is u,n char diaga = std::get<3>(GetParam()); @@ -64,12 +65,13 @@ TEST_P(dtrsvTest, RandomData) gtint_t n = std::get<4>(GetParam()); // specifies alpha value T alpha = std::get<5>(GetParam()); - // stride size for x: + // increment for x(incx): gtint_t incx = std::get<6>(GetParam()); // lda increment. // If increment is zero, then the array size matches the matrix size. // If increment are nonnegative, the array size is bigger than the matrix size. gtint_t lda_inc = std::get<7>(GetParam()); + bool is_mem_test = std::get<8>(GetParam()); // Set the threshold for the errors: // Check gtestsuite trsv.h or netlib source code for reminder of the @@ -84,62 +86,80 @@ TEST_P(dtrsvTest, RandomData) //---------------------------------------------------------- // Call test body using these parameters //---------------------------------------------------------- - test_trsv( storage, uploa, transa, diaga, n, alpha, lda_inc, incx, thresh ); + test_trsv( storage, uploa, transa, diaga, n, alpha, lda_inc, incx, thresh, is_mem_test); } -class dtrsvTestPrint { +class dtrsvPrint { public: std::string operator()( - testing::TestParamInfo> str) const { - char sfm = std::get<0>(str.param); - char uploa = std::get<1>(str.param); - char transa = std::get<2>(str.param); - char diaga = std::get<3>(str.param); - gtint_t n = std::get<4>(str.param); - double alpha = std::get<5>(str.param); - gtint_t incx = std::get<6>(str.param); - gtint_t ld_inc = std::get<7>(str.param); + testing::TestParamInfo> str) const { + char sfm = std::get<0>(str.param); + char uploa = std::get<1>(str.param); + char transa = std::get<2>(str.param); + char diaga = std::get<3>(str.param); + gtint_t n = std::get<4>(str.param); + double alpha = std::get<5>(str.param); + gtint_t incx = std::get<6>(str.param); + gtint_t ld_inc = std::get<7>(str.param); + bool is_mem_test = std::get<8>(str.param); #ifdef TEST_BLAS - std::string str_name = "dtrsv_"; + std::string str_name = "blas_"; #elif TEST_CBLAS - std::string str_name = "cblas_dtrsv"; + std::string str_name = "cblas_"; #else //#elif TEST_BLIS_TYPED - std::string str_name = "bli_dtrsv"; + std::string str_name = "bli_"; #endif - str_name = str_name + "_" + sfm; - str_name = str_name + "_" + uploa+transa; - str_name = str_name + "_d" + diaga; - str_name = str_name + "_" + std::to_string(n); - std::string alpha_str = ( alpha > 0) ? std::to_string(int(alpha)) : ("m" + std::to_string(int(std::abs(alpha)))); - str_name = str_name + "_a" + alpha_str; + str_name = str_name + "stor_" + sfm; + str_name = str_name + "_uplo_" + uploa; + str_name = str_name + "_transa_" + transa; + str_name = str_name + "_diaga_" + diaga; + str_name = str_name + "_n_" + std::to_string(n); + std::string alpha_str = testinghelpers::get_value_string(alpha); + str_name = str_name + "_alpha_" + alpha_str; std::string incx_str = ( incx > 0) ? std::to_string(incx) : "m" + std::to_string(std::abs(incx)); - str_name = str_name + "_" + incx_str; - str_name = str_name + "_" + std::to_string(ld_inc); + str_name = str_name + "_incx_" + incx_str; + str_name = str_name + "_lda_" + std::to_string( + testinghelpers::get_leading_dimension( sfm, transa, n, n, ld_inc ) + ); + str_name = str_name + (is_mem_test ? "_mem_test_enabled" : "_mem_test_disabled"); return str_name; } }; -// Black box testing. INSTANTIATE_TEST_SUITE_P( - Blackbox, - dtrsvTest, + Native, + dtrsvAPI, ::testing::Combine( ::testing::Values('c' #ifndef TEST_BLAS - ,'r' + ,'r' #endif ), // storage format ::testing::Values('u','l'), // uploa ::testing::Values('n','t'), // transa ::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG - ::testing::Range(gtint_t(10), gtint_t(31), 10), // n - ::testing::Values( 1.0 -#ifdef TEST_BLIS_TYPED - , -2.0 + ::testing::Values(gtint_t(32), + gtint_t(24), + gtint_t(8), + gtint_t(4), + gtint_t(2), + gtint_t(1), + gtint_t(15), + gtint_t(98), + gtint_t(173), + gtint_t(211) + ), // n + ::testing::Values( 1.0 // Only blis types api supports +#ifdef TEST_BLIS_TYPED // values of alpha other than 1 + , -2.2, 5.4, -1.0, 0.0 #endif ), // alpha - ::testing::Values(gtint_t(1)), // stride size for x - ::testing::Values(gtint_t(0), gtint_t(2)) // increment to the leading dim of a + ::testing::Values(gtint_t(-153), gtint_t(-10), + gtint_t(-2), gtint_t(-1), + gtint_t( 1), gtint_t( 2), + gtint_t(14), gtint_t(433)), // incx + ::testing::Values(gtint_t(0), gtint_t(10), gtint_t(358)), // increment to the leading dim of a + ::testing::Values(false, true) // is memory test ), - ::dtrsvTestPrint() + ::dtrsvPrint() ); diff --git a/gtestsuite/testsuite/level2/trsv/test_trsv.h b/gtestsuite/testsuite/level2/trsv/test_trsv.h index 226639720..3dd136549 100644 --- a/gtestsuite/testsuite/level2/trsv/test_trsv.h +++ b/gtestsuite/testsuite/level2/trsv/test_trsv.h @@ -4,7 +4,7 @@ An object-based framework for developing high-performance BLAS-like libraries. - Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. + Copyright (C) 2023-2024, Advanced Micro Devices, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -39,10 +39,24 @@ #include "inc/check_error.h" #include #include +#include "common/testing_helpers.h" template -void test_trsv( char storage, char uploa, char transa, char diaga, gtint_t n, - T alpha, gtint_t lda_inc, gtint_t incx, double thresh ) +void test_trsv( + char storage, + char uploa, + char transa, + char diaga, + gtint_t n, + T alpha, + gtint_t lda_inc, + gtint_t incx, + double thresh, + bool is_memory_test = false, + bool is_evt_test = false, + T evt_x = T{0}, + T evt_a = T{0} + ) { // Compute the leading dimensions for matrix size calculation. gtint_t lda = testinghelpers::get_leading_dimension( storage, transa, n, n, lda_inc ); @@ -50,25 +64,85 @@ void test_trsv( char storage, char uploa, char transa, char diaga, gtint_t n, //---------------------------------------------------------- // Initialize matrics with random integer numbers. //---------------------------------------------------------- - std::vector a = testinghelpers::get_random_matrix( 1, 5, storage, transa, n, n, lda ); - std::vector x = testinghelpers::get_random_vector( 1, 3, n, incx ); - testinghelpers::make_triangular( storage, uploa, n, a.data(), lda ); + dim_t size_a = testinghelpers::matsize(storage, transa, n, n, lda) * sizeof(T); - // Create a copy of c so that we can check reference results. - std::vector x_ref(x); + // Buffers for A matrix and X vector are always unaligned + testinghelpers::ProtectedBuffer a(size_a, false, is_memory_test ); + testinghelpers::datagenerators::randomgenerators( 1, 5, storage, n, n, (T*)(a.greenzone_1), transa, lda ); + + dim_t size_x = testinghelpers::buff_dim(n, incx) * sizeof(T); + testinghelpers::ProtectedBuffer x(size_x, false, is_memory_test ); + testinghelpers::datagenerators::randomgenerators( 1, 3, n, incx, (T*)(x.greenzone_1) ); + + T* a_ptr = (T*)(a.greenzone_1); + T* x_ptr = (T*)(x.greenzone_1); + + // Make A matix diagonal dominant to make sure that algorithm doesn't diverge + // This makes sure that the TRSV problem is solvable + for ( dim_t a_dim = 0; a_dim < n; ++a_dim ) + { + a_ptr[ a_dim + (a_dim* lda) ] = a_ptr[ a_dim + (a_dim* lda) ] * T{10}; + } + + // add extreme values to the X vector + if ( is_evt_test ) + { + x_ptr[ (rand() % n) * std::abs(incx) ] = evt_x; + } + + // add extreme values to the A matrix + if ( is_evt_test ) + { + dim_t n_idx = rand() % n; + dim_t m_idx = std::max((dim_t)0, n_idx - 1); + a_ptr[ m_idx + (n_idx * lda) ] = evt_a; + a_ptr[ m_idx + (m_idx *lda) ] = evt_a; + } + + // skipped making A triangular + // A matrix being a non triangular matrix could be a better test + // because we are exepcted to read only from the upper or lower triangular + // part of the data, contents of the rest of the matrix should not change the + // result. + // testinghelpers::make_triangular( storage, uploa, n, a_ptr, lda ); + + // Create a copy of x so that we can check reference results. + std::vector x_ref(testinghelpers::buff_dim(n, incx)); + memcpy(x_ref.data(), x_ptr, size_x); //---------------------------------------------------------- // Call BLIS function //---------------------------------------------------------- - trsv( storage, uploa, transa, diaga, n, &alpha, a.data(), lda, x.data(), incx ); + // add signal handler for segmentation fault + testinghelpers::ProtectedBuffer::start_signal_handler(); + try + { + trsv( storage, uploa, transa, diaga, n, &alpha, a_ptr, lda, x_ptr, incx ); + if (is_memory_test) + { + memcpy(a.greenzone_2, a.greenzone_1, size_a); + memcpy(x.greenzone_2, x_ref.data(), size_x); + trsv( storage, uploa, transa, diaga, n, &alpha, (T*)a.greenzone_2, lda, (T*)x.greenzone_2, incx ); + } + } + catch(const std::exception& e) + { + // reset to default signal handler + testinghelpers::ProtectedBuffer::stop_signal_handler(); + + // show failure in case seg fault was detected + FAIL() << "Memory Test Failed"; + } + // reset to default signal handler + testinghelpers::ProtectedBuffer::stop_signal_handler(); //---------------------------------------------------------- // Call reference implementation. //---------------------------------------------------------- - testinghelpers::ref_trsv( storage, uploa, transa, diaga, n, &alpha, a.data(), lda, x_ref.data(), incx ); + testinghelpers::ref_trsv( storage, uploa, transa, diaga, n, &alpha, a_ptr, lda, x_ref.data(), incx ); //---------------------------------------------------------- // check component-wise error. //---------------------------------------------------------- - computediff( n, x.data(), x_ref.data(), incx, thresh ); + computediff( n, x_ptr, x_ref.data(), incx, thresh, is_evt_test ); }