GTestSuite: Packed APIs (hpmv, spmv, tpmv, tpsv)

Create gtestsuite programs for subset of packed matrix APIs. Priority is to
create framework with a basic set of tests - refinement of problem sizes
can be investigated later.

AMD-Internal: [CPUPL-7386]
This commit is contained in:
Smyth, Edward
2026-01-16 12:08:36 +00:00
committed by GitHub
parent 72e0c001f2
commit c32247678c
37 changed files with 6198 additions and 1 deletions

View File

@@ -0,0 +1,55 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* hpmv performs the matrix-vector operation
* y := alpha*A*x + beta*y
* where alpha and beta are scalars, x and y are n element vectors and
* A is an n by n packed Hermitian matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_hpmv( char storage, char uploa, gtint_t n,
T* alpha, T *ap, T *xp, gtint_t incx, T* beta,
T *yp, gtint_t incy );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,55 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* spmv performs the matrix-vector operation
* y := alpha*A*x + beta*y
* where alpha and beta are scalars, x and y are n element vectors and
* A is an n by n packed symmetric matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_spmv( char storage, char uploa, gtint_t n,
T* alpha, T *ap, T *xp, gtint_t incx, T* beta,
T *yp, gtint_t incy );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,54 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* tpmv performs one of the matrix-vector operations
* x := transa(A) * x
* where x is an n element vector and A is an n by n unit, or non-unit,
* upper or lower packed triangular matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_tpmv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,55 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* tpsv Solves a triangular system of equations with a single value for the
* right side
* b := inv(transa(A)) * x_orig
* where b and x are n element vectors and A is an n by n unit, or non-unit,
* upper or lower packed triangular matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_tpsv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,94 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "blis.h"
#include "level2/ref_hpmv.h"
/*
* ==========================================================================
* hpmv performs the matrix-vector operation
* y := alpha*A*x + beta*y
* where alpha and beta are scalars, x and y are n element vectors and
* A is an n by n packed Hermitian matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_hpmv( char storage, char uploa, gtint_t n,
T* alpha, T *ap, T *xp, gtint_t incx, T* beta,
T *yp, gtint_t incy )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_uplo( uploa, &cblas_uploa );
typedef void (*Fptr_ref_cblas_hpmv)( const CBLAS_ORDER, const CBLAS_UPLO, const f77_int,
const T*, const T*, const T*, f77_int, const T*, T*, f77_int);
Fptr_ref_cblas_hpmv ref_cblas_hpmv;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(scomplex))
{
ref_cblas_hpmv = (Fptr_ref_cblas_hpmv)refCBLASModule.loadSymbol("cblas_chpmv");
}
else if (typeid(T) == typeid(dcomplex))
{
ref_cblas_hpmv = (Fptr_ref_cblas_hpmv)refCBLASModule.loadSymbol("cblas_zhpmv");
}
else
{
throw std::runtime_error("Error in ref_hpmv.cpp: Invalid typename is passed to function template.");
}
if (!ref_cblas_hpmv) {
throw std::runtime_error("Error in ref_hpmv.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_hpmv( cblas_order, cblas_uploa, n, alpha, ap, xp, incx, beta, yp, incy );
}
// Explicit template instantiations
template void ref_hpmv<scomplex>( char, char, gtint_t, scomplex *,
scomplex *, scomplex *, gtint_t, scomplex *, scomplex *, gtint_t );
template void ref_hpmv<dcomplex>( char, char, gtint_t, dcomplex *,
dcomplex *, dcomplex *, gtint_t, dcomplex *, dcomplex *, gtint_t );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,92 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "blis.h"
#include "level2/ref_spmv.h"
/*
* ==========================================================================
* spmv performs the matrix-vector operation
* y := alpha*A*x + beta*y
* where alpha and beta are scalars, x and y are n element vectors and
* A is an n by n packed symmetric matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_spmv( char storage, char uploa, gtint_t n,
T *alpha, T *ap, T *xp, gtint_t incx, T *beta,
T *yp, gtint_t incy )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_uplo( uploa, &cblas_uploa );
typedef void (*Fptr_ref_cblas_spmv)( const CBLAS_ORDER, const CBLAS_UPLO, const f77_int,
const T, const T*, const T*, f77_int, const T, T*, f77_int);
Fptr_ref_cblas_spmv ref_cblas_spmv;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(float))
{
ref_cblas_spmv = (Fptr_ref_cblas_spmv)refCBLASModule.loadSymbol("cblas_sspmv");
}
else if (typeid(T) == typeid(double))
{
ref_cblas_spmv = (Fptr_ref_cblas_spmv)refCBLASModule.loadSymbol("cblas_dspmv");
}
else
{
throw std::runtime_error("Error in ref_spmv.cpp: Invalid typename is passed to function template.");
}
if (!ref_cblas_spmv) {
throw std::runtime_error("Error in ref_spmv.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_spmv( cblas_order, cblas_uploa, n, *alpha, ap, xp, incx, *beta, yp, incy );
}
// Explicit template instantiations
template void ref_spmv<float>( char, char, gtint_t, float *,
float *, float *, gtint_t, float *, float *, gtint_t );
template void ref_spmv<double>( char, char, gtint_t, double *,
double *, double *, gtint_t, double *, double *, gtint_t );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,109 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "blis.h"
#include "level2/ref_tpmv.h"
/*
* ==========================================================================
* tpmv performs one of the matrix-vector operations
* x := transa(A) * x
* where x is an n element vector and A is an n by n unit, or non-unit,
* upper or lower packed triangular matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_tpmv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
enum CBLAS_TRANSPOSE cblas_trans;
enum CBLAS_DIAG cblas_diaga;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_uplo( uploa, &cblas_uploa );
char_to_cblas_trans( transa, &cblas_trans );
char_to_cblas_diag( diaga, &cblas_diaga );
typedef void (*Fptr_ref_cblas_tpmv)( const CBLAS_ORDER, const CBLAS_UPLO,
const CBLAS_TRANSPOSE, CBLAS_DIAG ,
f77_int, const T*, T*, f77_int );
Fptr_ref_cblas_tpmv ref_cblas_tpmv;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(float))
{
ref_cblas_tpmv = (Fptr_ref_cblas_tpmv)refCBLASModule.loadSymbol("cblas_stpmv");
}
else if (typeid(T) == typeid(double))
{
ref_cblas_tpmv = (Fptr_ref_cblas_tpmv)refCBLASModule.loadSymbol("cblas_dtpmv");
}
else if (typeid(T) == typeid(scomplex))
{
ref_cblas_tpmv = (Fptr_ref_cblas_tpmv)refCBLASModule.loadSymbol("cblas_ctpmv");
}
else if (typeid(T) == typeid(dcomplex))
{
ref_cblas_tpmv = (Fptr_ref_cblas_tpmv)refCBLASModule.loadSymbol("cblas_ztpmv");
}
else
{
throw std::runtime_error("Error in ref_tpmv.cpp: Invalid typename is passed to function template.");
}
if (!ref_cblas_tpmv) {
throw std::runtime_error("Error in ref_tpmv.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_tpmv( cblas_order, cblas_uploa, cblas_trans, cblas_diaga, n, ap, xp, incx );
}
// Explicit template instantiations
template void ref_tpmv<float>( char , char , char , char , gtint_t ,
float *, float *, gtint_t );
template void ref_tpmv<double>( char , char , char , char , gtint_t ,
double *, double *, gtint_t );
template void ref_tpmv<scomplex>( char , char , char , char , gtint_t ,
scomplex *, scomplex *, gtint_t );
template void ref_tpmv<dcomplex>( char , char , char , char , gtint_t ,
dcomplex *, dcomplex *, gtint_t );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,108 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "blis.h"
#include "level2/ref_tpsv.h"
/*
* ==========================================================================
* tpsv Solves a triangular system of equations with a single value for the
* right side
* b := inv(transa(A)) * x_orig
* where b and x are n element vectors and A is an n by n unit, or non-unit,
* upper or lower packed triangular matrix.
* ==========================================================================
**/
namespace testinghelpers {
template <typename T>
void ref_tpsv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
enum CBLAS_TRANSPOSE cblas_trans;
enum CBLAS_DIAG cblas_diaga;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_uplo( uploa, &cblas_uploa );
char_to_cblas_trans( transa, &cblas_trans );
char_to_cblas_diag( diaga, &cblas_diaga );
typedef void (*Fptr_ref_cblas_tpsv)( const CBLAS_ORDER, const CBLAS_UPLO,
const CBLAS_TRANSPOSE, CBLAS_DIAG ,
f77_int, const T*, T*, f77_int );
Fptr_ref_cblas_tpsv ref_cblas_tpsv;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(float))
{
ref_cblas_tpsv = (Fptr_ref_cblas_tpsv)refCBLASModule.loadSymbol("cblas_stpsv");
}
else if (typeid(T) == typeid(double))
{
ref_cblas_tpsv = (Fptr_ref_cblas_tpsv)refCBLASModule.loadSymbol("cblas_dtpsv");
}
else if (typeid(T) == typeid(scomplex))
{
ref_cblas_tpsv = (Fptr_ref_cblas_tpsv)refCBLASModule.loadSymbol("cblas_ctpsv");
}
else if (typeid(T) == typeid(dcomplex))
{
ref_cblas_tpsv = (Fptr_ref_cblas_tpsv)refCBLASModule.loadSymbol("cblas_ztpsv");
}
else
{
throw std::runtime_error("Error in ref_tpsv.cpp: Invalid typename is passed to function template.");
}
if (!ref_cblas_tpsv) {
throw std::runtime_error("Error in ref_tpsv.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_tpsv( cblas_order, cblas_uploa, cblas_trans, cblas_diaga, n, ap, xp, incx );
}
// Explicit template instantiations
template void ref_tpsv<float>( char , char , char , char , gtint_t ,
float *, float *, gtint_t );
template void ref_tpsv<double>( char , char , char , char , gtint_t ,
double *, double *, gtint_t );
template void ref_tpsv<scomplex>( char , char , char , char , gtint_t ,
scomplex *, scomplex *, gtint_t );
template void ref_tpsv<dcomplex>( char , char , char , char , gtint_t ,
dcomplex *, dcomplex *, gtint_t );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,596 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/hpmv/test_hpmv.h"
#include "common/wrong_inputs_helpers.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
template <typename T>
class hpmv_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<scomplex, dcomplex> TypeParam;
TYPED_TEST_SUITE(hpmv_IIT_ERS, TypeParam);
using namespace testinghelpers::IIT;
#if defined(TEST_CBLAS)
#define INFO_OFFSET 1
#else
#define INFO_OFFSET 0
#endif
#if defined(TEST_CBLAS)
TYPED_TEST(hpmv_IIT_ERS, invalid_storage)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
hpmv<T>( 'x', UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( 'x', UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
}
#endif
#if defined(TEST_BLAS_LIKE) || defined(TEST_CBLAS)
/*
Incorrect Input Testing(IIT)
BLAS exceptions get triggered in the following cases(for HPMV):
1. When UPLO != 'N' || UPLO != 'T' || UPLO != 'C' (info = 1)
3. When n < 0 (info = 2)
4. When incx = 0 (info = 6)
5. When incy = 0 (info = 9)
*/
TYPED_TEST(hpmv_IIT_ERS, invalid_UPLO)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
hpmv<T>( STORAGE, 'p', N, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
hpmv<T>( STORAGE, 'p', N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, 'p', N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
}
TYPED_TEST(hpmv_IIT_ERS, n_lt_zero)
{
using T = TypeParam;
gtint_t invalid_n = -1;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
hpmv<T>( STORAGE, UPLO, invalid_n, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 2 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 2 );
#endif
}
TYPED_TEST(hpmv_IIT_ERS, incx_eq_zero)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
hpmv<T>( STORAGE, UPLO, N, nullptr, nullptr,
nullptr, 0, nullptr, nullptr, incy );
#else
hpmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, 0, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 6 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), 0, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 6 );
#endif
}
TYPED_TEST(hpmv_IIT_ERS, incy_eq_zero)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
hpmv<T>( STORAGE, UPLO, N, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, 0 );
#else
hpmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, 0 );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 9 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), 0 );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 9 );
#endif
}
/*
BLAS Early Return Scenarios(ERS):
hpmv is expected to return early in the following cases:
1. m || n = 0
2. alpha = 0 && beta = 1
*/
// n = 0
TYPED_TEST(hpmv_IIT_ERS, n_eq_zero)
{
using T = TypeParam;
gtint_t invalid_n = 0;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha = T{1.3};
T beta = T{0.7};
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
hpmv<T>( STORAGE, UPLO, invalid_n, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// n = 0, with unit alpha and beta
TYPED_TEST(hpmv_IIT_ERS, n_eq_zero_UnitAlphaBeta)
{
using T = TypeParam;
gtint_t invalid_n = 0;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and unit beta
TYPED_TEST(hpmv_IIT_ERS, ZeroAlpha_UnitBeta)
{
using T = TypeParam;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
hpmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and zero beta - set y to zero
TYPED_TEST(hpmv_IIT_ERS, ZeroAlpha_ZeroBeta)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
testinghelpers::initzero<T>( beta );
// Vector y should not be read, only set.
std::vector<T> y( testinghelpers::buff_dim(N, incy) );
testinghelpers::set_vector( N, incy, y.data(), testinghelpers::aocl_extreme<T>() );
std::vector<T> y2(y);
// Create a zero vector, since the output for alpha = beta = 0 should be a
// zero vector.
std::vector<T> zero_vec = testinghelpers::get_random_vector<T>( 0, 0, N, incy );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
hpmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, y2.data(), incy );
computediff<T>( "y", N, y2.data(), zero_vec.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 0, 1, N, incx );
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), zero_vec.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and non-zero/non-unit beta - scale y only
TYPED_TEST(hpmv_IIT_ERS, ZeroAlpha_OtherBeta)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
beta = T{2.0};
double thresh = testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 0, 1, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 0, 1, N, incy );
std::vector<T> y_ref(y);
std::vector<T> y2(y);
testinghelpers::ref_hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y_ref.data(), incy );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
hpmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, y2.data(), incy );
computediff<T>( "y", N, y2.data(), y_ref.data(), incy, thresh);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy, thresh);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
#endif

View File

@@ -0,0 +1,170 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/hpmv/test_hpmv.h"
class chpmvGeneric :
public ::testing::TestWithParam<std::tuple<char,
char,
gtint_t,
scomplex,
scomplex,
gtint_t,
gtint_t>> {};
TEST_P( chpmvGeneric, API )
{
using T = scomplex;
//----------------------------------------------------------
// 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());
// matrix size n
gtint_t n = std::get<2>(GetParam());
// specifies alpha value
T alpha = std::get<3>(GetParam());
// specifies beta value
T beta = std::get<4>(GetParam());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// stride size for y
gtint_t incy = std::get<6>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite hpmv.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.
// No adjustment applied yet for complex data.
double thresh;
if (n == 0)
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>() && (beta == testinghelpers::ZERO<T>() || beta == testinghelpers::ONE<T>()))
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>())
thresh = testinghelpers::getEpsilon<T>();
else
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 1.2;
#endif
thresh = adj*(3*n+1)*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
chpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(scomplex{0.0, 0.0},scomplex{1.0, 0.0},
scomplex{-1.0, 0.0},scomplex{1.0, -2.0}), // alpha
::testing::Values(scomplex{0.0, 0.0},scomplex{1.0, 0.0},
scomplex{-1.0, 0.0},scomplex{1.0, -2.0}), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::hpmvGenericPrint<scomplex>()
);
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
chpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(scomplex{0.0, 0.0},scomplex{1.0, 0.0},
scomplex{-1.0, 0.0},scomplex{1.0, -2.0}), // alpha
::testing::Values(scomplex{0.0, 0.0},scomplex{1.0, 0.0},
scomplex{-1.0, 0.0},scomplex{1.0, -2.0}), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::hpmvGenericPrint<scomplex>()
);

View File

@@ -0,0 +1,181 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
/**
* @brief Performs the operation:
* y := alpha*A*x + beta*y
* @param[in] storage specifies the form of storage in the memory matrix A
* @param[in] uploa specifies whether the upper or lower triangular part of the array A
* @param[in] n specifies the number of rows of the matrix A
* @param[in] alpha specifies the scalar alpha.
* @param[in] ap specifies pointer which points to the first element of ap
* @param[in] xp specifies pointer which points to the first element of xp
* @param[in] incx specifies storage spacing between elements of xp.
* @param[in] beta specifies the scalar beta.
* @param[in,out] yp specifies pointer which points to the first element of yp
* @param[in] incy specifies storage spacing between elements of yp.
*/
template<typename T>
static void hpmv_( char uploa, gtint_t n, T* alpha, T* ap,
T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
if constexpr (std::is_same<T, scomplex>::value)
chpmv_( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else if constexpr (std::is_same<T, dcomplex>::value)
zhpmv_( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: Invalid typename in hpmv_().");
}
template<typename T>
static void hpmv_blis_impl( char uploa, gtint_t n, T* alpha, T* ap,
T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
if constexpr (std::is_same<T, scomplex>::value)
chpmv_blis_impl( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else if constexpr (std::is_same<T, dcomplex>::value)
zhpmv_blis_impl( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: Invalid typename in hpmv_blis_impl().");
}
template<typename T>
static void cblas_hpmv( char storage, char uploa, gtint_t n, T* alpha,
T* ap, T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uplo;
testinghelpers::char_to_cblas_order( storage, &cblas_order );
testinghelpers::char_to_cblas_uplo( uploa, &cblas_uplo );
if constexpr (std::is_same<T, scomplex>::value)
cblas_chpmv( cblas_order, cblas_uplo, n, alpha, ap, xp, incx, beta, yp, incy );
else if constexpr (std::is_same<T, dcomplex>::value)
cblas_zhpmv( cblas_order, cblas_uplo, n, alpha, ap, xp, incx, beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: Invalid typename in cblas_hpmv().");
}
template<typename T>
static void hpmv( char storage, char uploa, gtint_t n,
T* alpha, T* ap, T* xp, gtint_t incx, T* beta, T* yp,
gtint_t incy )
{
#ifdef TEST_UPPERCASE_ARGS
storage = static_cast<char>(std::toupper(static_cast<unsigned char>(storage)));
uploa = static_cast<char>(std::toupper(static_cast<unsigned char>(uploa)));
#endif
#ifdef TEST_INPUT_ARGS
// Create copy of scalar input values so we can check that they are not altered.
char storage_cpy = storage;
char uploa_cpy = uploa;
gtint_t n_cpy = n;
T* alpha_cpy = alpha;
gtint_t incx_cpy = incx;
T* beta_cpy = beta;
gtint_t incy_cpy = incy;
// Create copy of input arrays so we can check that they are not altered.
T* ap_cpy = nullptr;
gtint_t size_ap = ( n * ( n + 1 ) ) / 2;
if (ap && size_ap > 0)
{
ap_cpy = new T[size_ap];
memcpy( ap_cpy, ap, size_ap * sizeof( T ) );
}
T* xp_cpy = nullptr;
gtint_t size_xp;
size_xp = testinghelpers::buff_dim( n, incx );
{
xp_cpy = new T[size_xp];
memcpy( xp_cpy, xp, size_xp * sizeof( T ) );
}
#endif
#ifdef TEST_BLAS
if( storage == 'c' || storage == 'C' )
hpmv_<T>( uploa, n, alpha, ap, xp, incx, beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: BLAS interface cannot be tested for row-major order.");
#elif TEST_BLAS_BLIS_IMPL
if( storage == 'c' || storage == 'C' )
hpmv_blis_impl<T>( uploa, n, alpha, ap, xp, incx, beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: BLAS_BLIS_IMPL interface cannot be tested for row-major order.");
#elif TEST_CBLAS
cblas_hpmv<T>( storage, uploa, n, alpha, ap, xp, incx, beta, yp, incy );
#else
throw std::runtime_error("Error in testsuite/level2/hpmv.h: No interfaces are set to be tested.");
#endif
#ifdef TEST_INPUT_ARGS
//----------------------------------------------------------
// Check scalar inputs have not been modified.
//----------------------------------------------------------
computediff<char>( "storage", storage, storage_cpy );
computediff<char>( "uploa", uploa, uploa_cpy );
computediff<gtint_t>( "n", n, n_cpy );
if (alpha) computediff<T>( "alpha", *alpha, *alpha_cpy );
computediff<gtint_t>( "incx", incx, incx_cpy );
if (beta) computediff<T>( "beta", *beta, *beta_cpy );
computediff<gtint_t>( "incy", incy, incy_cpy );
//----------------------------------------------------------
// Bitwise-wise check array inputs have not been modified.
//----------------------------------------------------------
if (ap && size_ap > 0)
{
computediff<T>( "A", size_ap, ap, ap_cpy, false );
delete[] ap_cpy;
}
if (xp && size_xp > 0)
{
computediff<T>( "x", n, xp, xp_cpy, incx, true );
delete[] xp_cpy;
}
#endif
}

View File

@@ -0,0 +1,119 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "hpmv.h"
#include "level2/ref_hpmv.h"
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include "inc/data_pool.h"
template<typename T>
void test_hpmv( char storage, char uploa, gtint_t n,
T alpha, gtint_t incx, T beta, gtint_t incy, double thresh )
{
dim_t len_a = ( n * ( n + 1 ) ) / 2;
//----------------------------------------------------------
// Initialize matrices with random numbers.
//----------------------------------------------------------
// Set index based on n and incx to get varied data
get_pool<T, -2, 5>().set_index(n, incx);
get_pool<T, -3, 3>().set_index(n, incx);
std::vector<T> a = get_pool<T, -2, 5>().get_random_vector(len_a, 1);
// This will use the index from where it was
std::vector<T> x = get_pool<T, -3, 3>().get_random_vector(n, incx);
std::vector<T> y( testinghelpers::buff_dim(n, incy) );
if (beta != testinghelpers::ZERO<T>())
get_pool<T, -3, 3>().randomgenerators( n, incy, y.data() );
else
{
// Vector Y should not be read, only set.
testinghelpers::set_vector( n, incy, y.data(), testinghelpers::aocl_extreme<T>() );
}
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
hpmv<T>( storage, uploa, n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_hpmv<T>( storage, uploa, n, &alpha,
a.data(), x.data(), incx, &beta, y_ref.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", n, y.data(), y_ref.data(), incy, thresh );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// Test-case logger : Used to print the test-case details based on parameters
template <typename T>
class hpmvGenericPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,T,T,gtint_t,gtint_t>> str) const {
char storage = std::get<0>(str.param);
char uploa = std::get<1>(str.param);
gtint_t n = std::get<2>(str.param);
T alpha = std::get<3>(str.param);
T beta = std::get<4>(str.param);
gtint_t incx = std::get<5>(str.param);
gtint_t incy = std::get<6>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_alpha_" + testinghelpers::get_value_string(alpha);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
str_name += "_beta_" + testinghelpers::get_value_string(beta);
str_name += "_incy_" + testinghelpers::get_value_string(incy);
return str_name;
}
};

View File

@@ -0,0 +1,169 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/hpmv/test_hpmv.h"
class zhpmvGeneric :
public ::testing::TestWithParam<std::tuple<char,
char,
gtint_t,
dcomplex,
dcomplex,
gtint_t,
gtint_t>> {};
TEST_P( zhpmvGeneric, API )
{
using T = dcomplex;
//----------------------------------------------------------
// 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());
// matrix size n
gtint_t n = std::get<2>(GetParam());
// specifies alpha value
T alpha = std::get<3>(GetParam());
// specifies beta value
T beta = std::get<4>(GetParam());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// stride size for y
gtint_t incy = std::get<6>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite hpmv.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.
// With adjustment applied for complex data.
double thresh;
if (n == 0)
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>() && (beta == testinghelpers::ZERO<T>() || beta == testinghelpers::ONE<T>()))
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>())
thresh = testinghelpers::getEpsilon<T>();
else
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 2.4;
#endif
thresh = adj*(3*n+1)*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_hpmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
zhpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(dcomplex{0.0, 0.0},dcomplex{1.0, 0.0},
dcomplex{-1.0, 0.0},dcomplex{1.0, -2.0}), // alpha
::testing::Values(dcomplex{0.0, 0.0},dcomplex{1.0, 0.0},
dcomplex{-1.0, 0.0},dcomplex{1.0, -2.0}), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::hpmvGenericPrint<dcomplex>()
);
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
zhpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(dcomplex{0.0, 0.0},dcomplex{1.0, 0.0},
dcomplex{-1.0, 0.0},dcomplex{1.0, -2.0}), // alpha
::testing::Values(dcomplex{0.0, 0.0},dcomplex{1.0, 0.0},
dcomplex{-1.0, 0.0},dcomplex{1.0, -2.0}), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::hpmvGenericPrint<dcomplex>()
);

View File

@@ -0,0 +1,596 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/spmv/test_spmv.h"
#include "common/wrong_inputs_helpers.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
template <typename T>
class spmv_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<float, double> TypeParam;
TYPED_TEST_SUITE(spmv_IIT_ERS, TypeParam);
using namespace testinghelpers::IIT;
#if defined(TEST_CBLAS)
#define INFO_OFFSET 1
#else
#define INFO_OFFSET 0
#endif
#if defined(TEST_CBLAS)
TYPED_TEST(spmv_IIT_ERS, invalid_storage)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
spmv<T>( 'x', UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( 'x', UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
}
#endif
#if defined(TEST_BLAS_LIKE) || defined(TEST_CBLAS)
/*
Incorrect Input Testing(IIT)
BLAS exceptions get triggered in the following cases(for SPMV):
1. When UPLO != 'N' || UPLO != 'T' || UPLO != 'C' (info = 1)
3. When n < 0 (info = 2)
4. When incx = 0 (info = 6)
5. When incy = 0 (info = 9)
*/
TYPED_TEST(spmv_IIT_ERS, invalid_UPLO)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
spmv<T>( STORAGE, 'p', N, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
spmv<T>( STORAGE, 'p', N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, 'p', N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
}
TYPED_TEST(spmv_IIT_ERS, n_lt_zero)
{
using T = TypeParam;
gtint_t invalid_n = -1;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
spmv<T>( STORAGE, UPLO, invalid_n, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 2 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 2 );
#endif
}
TYPED_TEST(spmv_IIT_ERS, incx_eq_zero)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
spmv<T>( STORAGE, UPLO, N, nullptr, nullptr,
nullptr, 0, nullptr, nullptr, incy );
#else
spmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, 0, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 6 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), 0, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 6 );
#endif
}
TYPED_TEST(spmv_IIT_ERS, incy_eq_zero)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
spmv<T>( STORAGE, UPLO, N, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, 0 );
#else
spmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, 0 );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 9 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), 0 );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 9 );
#endif
}
/*
BLAS Early Return Scenarios(ERS):
spmv is expected to return early in the following cases:
1. m || n = 0
2. alpha = 0 && beta = 1
*/
// n = 0
TYPED_TEST(spmv_IIT_ERS, n_eq_zero)
{
using T = TypeParam;
gtint_t invalid_n = 0;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha = T{1.3};
T beta = T{0.7};
// Test with nullptr for all suitable arguments that shouldn't be accessed.
#if defined(TEST_BLAS_LIKE)
spmv<T>( STORAGE, UPLO, invalid_n, nullptr, nullptr,
nullptr, incx, nullptr, nullptr, incy );
#else
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#endif
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// n = 0, with unit alpha and beta
TYPED_TEST(spmv_IIT_ERS, n_eq_zero_UnitAlphaBeta)
{
using T = TypeParam;
gtint_t invalid_n = 0;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, invalid_n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and unit beta
TYPED_TEST(spmv_IIT_ERS, ZeroAlpha_UnitBeta)
{
using T = TypeParam;
gtint_t incx = 1;
gtint_t incy = 1;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
testinghelpers::initone<T>( beta );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
spmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, nullptr, incy );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 1, 3, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 1, 3, N, incy );
// Create a copy of c so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and zero beta - set y to zero
TYPED_TEST(spmv_IIT_ERS, ZeroAlpha_ZeroBeta)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
testinghelpers::initzero<T>( beta );
// Vector y should not be read, only set.
std::vector<T> y( testinghelpers::buff_dim(N, incy) );
testinghelpers::set_vector( N, incy, y.data(), testinghelpers::aocl_extreme<T>() );
std::vector<T> y2(y);
// Create a zero vector, since the output for alpha = beta = 0 should be a
// zero vector.
std::vector<T> zero_vec = testinghelpers::get_random_vector<T>( 0, 0, N, incy );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
spmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, y2.data(), incy );
computediff<T>( "y", N, y2.data(), zero_vec.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 0, 1, N, incx );
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), zero_vec.data(), incy);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// zero alpha and non-zero/non-unit beta - scale y only
TYPED_TEST(spmv_IIT_ERS, ZeroAlpha_OtherBeta)
{
using T = TypeParam;
gtint_t incx = 3;
gtint_t incy = 3;
T alpha, beta;
testinghelpers::initzero<T>( alpha );
beta = T{2.0};
double thresh = testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Initialize matrices with random integer numbers.
//----------------------------------------------------------
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( 1, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>( 0, 1, N, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( 0, 1, N, incy );
std::vector<T> y_ref(y);
std::vector<T> y2(y);
testinghelpers::ref_spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y_ref.data(), incy );
// Test with nullptr for all suitable arguments that shouldn't be accessed.
spmv<T>( STORAGE, UPLO, N, &alpha, nullptr,
nullptr, incx, &beta, y2.data(), incy );
computediff<T>( "y", N, y2.data(), y_ref.data(), incy, thresh);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( STORAGE, UPLO, N, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", N, y.data(), y_ref.data(), incy, thresh);
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
#endif

View File

@@ -0,0 +1,164 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/spmv/test_spmv.h"
class dspmvGeneric :
public ::testing::TestWithParam<std::tuple<char,
char,
gtint_t,
double,
double,
gtint_t,
gtint_t>> {};
TEST_P( dspmvGeneric, API )
{
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());
// matrix size n
gtint_t n = std::get<2>(GetParam());
// specifies alpha value
T alpha = std::get<3>(GetParam());
// specifies beta value
T beta = std::get<4>(GetParam());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// stride size for y
gtint_t incy = std::get<6>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite spmv.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 if (alpha == testinghelpers::ZERO<T>() && (beta == testinghelpers::ZERO<T>() || beta == testinghelpers::ONE<T>()))
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>())
thresh = testinghelpers::getEpsilon<T>();
else
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.5;
#else
double adj = 2.5;
#endif
thresh = adj*(3*n+1)*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
dspmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // alpha
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::spmvGenericPrint<double>()
);
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
dspmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // alpha
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::spmvGenericPrint<double>()
);

View File

@@ -0,0 +1,181 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
/**
* @brief Performs the operation:
* y := alpha*A*x + beta*y
* @param[in] storage specifies the form of storage in the memory matrix A
* @param[in] uploa specifies whether the upper or lower triangular part of the array A
* @param[in] n specifies the number of rows of the matrix A
* @param[in] alpha specifies the scalar alpha.
* @param[in] ap specifies pointer which points to the first element of ap
* @param[in] xp specifies pointer which points to the first element of xp
* @param[in] incx specifies storage spacing between elements of xp.
* @param[in] beta specifies the scalar beta.
* @param[in,out] yp specifies pointer which points to the first element of yp
* @param[in] incy specifies storage spacing between elements of yp.
*/
template<typename T>
static void spmv_( char uploa, gtint_t n, T* alpha, T* ap,
T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
if constexpr (std::is_same<T, float>::value)
sspmv_( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else if constexpr (std::is_same<T, double>::value)
dspmv_( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else
throw std::runtime_error("Error in testsuite/level2/spmv.h: Invalid typename in spmv_().");
}
template<typename T>
static void spmv_blis_impl( char uploa, gtint_t n, T* alpha, T* ap,
T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
if constexpr (std::is_same<T, float>::value)
sspmv_blis_impl( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else if constexpr (std::is_same<T, double>::value)
dspmv_blis_impl( &uploa, &n, alpha, ap, xp, &incx, beta, yp, &incy );
else
throw std::runtime_error("Error in testsuite/level2/spmv.h: Invalid typename in spmv_blis_impl().");
}
template<typename T>
static void cblas_spmv( char storage, char uploa, gtint_t n, T* alpha,
T* ap, T* xp, gtint_t incx, T* beta, T* yp, gtint_t incy )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uplo;
testinghelpers::char_to_cblas_order( storage, &cblas_order );
testinghelpers::char_to_cblas_uplo( uploa, &cblas_uplo );
if constexpr (std::is_same<T, float>::value)
cblas_sspmv( cblas_order, cblas_uplo, n, *alpha, ap, xp, incx, *beta, yp, incy );
else if constexpr (std::is_same<T, double>::value)
cblas_dspmv( cblas_order, cblas_uplo, n, *alpha, ap, xp, incx, *beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/spmv.h: Invalid typename in cblas_spmv().");
}
template<typename T>
static void spmv( char storage, char uploa, gtint_t n,
T* alpha, T* ap, T* xp, gtint_t incx, T* beta, T* yp,
gtint_t incy )
{
#ifdef TEST_UPPERCASE_ARGS
storage = static_cast<char>(std::toupper(static_cast<unsigned char>(storage)));
uploa = static_cast<char>(std::toupper(static_cast<unsigned char>(uploa)));
#endif
#ifdef TEST_INPUT_ARGS
// Create copy of scalar input values so we can check that they are not altered.
char storage_cpy = storage;
char uploa_cpy = uploa;
gtint_t n_cpy = n;
T* alpha_cpy = alpha;
gtint_t incx_cpy = incx;
T* beta_cpy = beta;
gtint_t incy_cpy = incy;
// Create copy of input arrays so we can check that they are not altered.
T* ap_cpy = nullptr;
gtint_t size_ap = ( n * ( n + 1 ) ) / 2;
if (ap && size_ap > 0)
{
ap_cpy = new T[size_ap];
memcpy( ap_cpy, ap, size_ap * sizeof( T ) );
}
T* xp_cpy = nullptr;
gtint_t size_xp;
size_xp = testinghelpers::buff_dim( n, incx );
{
xp_cpy = new T[size_xp];
memcpy( xp_cpy, xp, size_xp * sizeof( T ) );
}
#endif
#ifdef TEST_BLAS
if( storage == 'c' || storage == 'C' )
spmv_<T>( uploa, n, alpha, ap, xp, incx, beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/spmv.h: BLAS interface cannot be tested for row-major order.");
#elif TEST_BLAS_BLIS_IMPL
if( storage == 'c' || storage == 'C' )
spmv_blis_impl<T>( uploa, n, alpha, ap, xp, incx, beta, yp, incy );
else
throw std::runtime_error("Error in testsuite/level2/spmv.h: BLAS_BLIS_IMPL interface cannot be tested for row-major order.");
#elif TEST_CBLAS
cblas_spmv<T>( storage, uploa, n, alpha, ap, xp, incx, beta, yp, incy );
#else
throw std::runtime_error("Error in testsuite/level2/spmv.h: No interfaces are set to be tested.");
#endif
#ifdef TEST_INPUT_ARGS
//----------------------------------------------------------
// Check scalar inputs have not been modified.
//----------------------------------------------------------
computediff<char>( "storage", storage, storage_cpy );
computediff<char>( "uploa", uploa, uploa_cpy );
computediff<gtint_t>( "n", n, n_cpy );
if (alpha) computediff<T>( "alpha", *alpha, *alpha_cpy );
computediff<gtint_t>( "incx", incx, incx_cpy );
if (beta) computediff<T>( "beta", *beta, *beta_cpy );
computediff<gtint_t>( "incy", incy, incy_cpy );
//----------------------------------------------------------
// Bitwise-wise check array inputs have not been modified.
//----------------------------------------------------------
if (ap && size_ap > 0)
{
computediff<T>( "A", size_ap, ap, ap_cpy, false );
delete[] ap_cpy;
}
if (xp && size_xp > 0)
{
computediff<T>( "x", n, xp, xp_cpy, incx, true );
delete[] xp_cpy;
}
#endif
}

View File

@@ -0,0 +1,164 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/spmv/test_spmv.h"
class sspmvGeneric :
public ::testing::TestWithParam<std::tuple<char,
char,
gtint_t,
float,
float,
gtint_t,
gtint_t>> {};
TEST_P( sspmvGeneric, API )
{
using T = float;
//----------------------------------------------------------
// 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());
// matrix size n
gtint_t n = std::get<2>(GetParam());
// specifies alpha value
T alpha = std::get<3>(GetParam());
// specifies beta value
T beta = std::get<4>(GetParam());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// stride size for y
gtint_t incy = std::get<6>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite spmv.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 if (alpha == testinghelpers::ZERO<T>() && (beta == testinghelpers::ZERO<T>() || beta == testinghelpers::ONE<T>()))
thresh = 0.0;
else if (alpha == testinghelpers::ZERO<T>())
thresh = testinghelpers::getEpsilon<T>();
else
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 3.4;
#else
double adj = 2.3;
#endif
thresh = adj*(3*n+1)*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_spmv<T>( storage, uploa, n, alpha, incx, beta, incy, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
sspmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // alpha
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::spmvGenericPrint<float>()
);
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
sspmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // alpha
::testing::Values( 0.0, 1.0, -1.0, 2.7 ), // beta
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)), // stride size for x
::testing::Values(gtint_t(1),gtint_t(-1),gtint_t(2)) // stride size for y
),
::spmvGenericPrint<float>()
);

View File

@@ -0,0 +1,119 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "spmv.h"
#include "level2/ref_spmv.h"
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include "inc/data_pool.h"
template<typename T>
void test_spmv( char storage, char uploa, gtint_t n,
T alpha, gtint_t incx, T beta, gtint_t incy, double thresh )
{
dim_t len_a = ( n * ( n + 1 ) ) / 2;
//----------------------------------------------------------
// Initialize matrices with random numbers.
//----------------------------------------------------------
// Set index based on n and incx to get varied data
get_pool<T, -2, 5>().set_index(n, incx);
get_pool<T, -3, 3>().set_index(n, incx);
std::vector<T> a = get_pool<T, -2, 5>().get_random_vector(len_a, 1);
// This will use the index from where it was
std::vector<T> x = get_pool<T, -3, 3>().get_random_vector(n, incx);
std::vector<T> y( testinghelpers::buff_dim(n, incy) );
if (beta != testinghelpers::ZERO<T>())
get_pool<T, -3, 3>().randomgenerators( n, incy, y.data() );
else
{
// Vector Y should not be read, only set.
testinghelpers::set_vector( n, incy, y.data(), testinghelpers::aocl_extreme<T>() );
}
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
spmv<T>( storage, uploa, n, &alpha, a.data(),
x.data(), incx, &beta, y.data(), incy );
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_spmv<T>( storage, uploa, n, &alpha,
a.data(), x.data(), incx, &beta, y_ref.data(), incy );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "y", n, y.data(), y_ref.data(), incy, thresh );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// Test-case logger : Used to print the test-case details based on parameters
template <typename T>
class spmvGenericPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,T,T,gtint_t,gtint_t>> str) const {
char storage = std::get<0>(str.param);
char uploa = std::get<1>(str.param);
gtint_t n = std::get<2>(str.param);
T alpha = std::get<3>(str.param);
T beta = std::get<4>(str.param);
gtint_t incx = std::get<5>(str.param);
gtint_t incy = std::get<6>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_alpha_" + testinghelpers::get_value_string(alpha);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
str_name += "_beta_" + testinghelpers::get_value_string(beta);
str_name += "_incy_" + testinghelpers::get_value_string(incy);
return str_name;
}
};

View File

@@ -0,0 +1,297 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "level2/tpmv/test_tpmv.h"
#include "inc/check_error.h"
#include "common/testing_helpers.h"
#include "common/wrong_inputs_helpers.h"
#include <stdexcept>
#include <algorithm>
#include <gtest/gtest.h>
template <typename T>
class tpmv_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam;
TYPED_TEST_SUITE(tpmv_IIT_ERS, TypeParam);
// Adding namespace to get default parameters(valid case) from testinghelpers/common/wrong_input_helpers.h.
using namespace testinghelpers::IIT;
#if defined(TEST_CBLAS)
#define INFO_OFFSET 1
#else
#define INFO_OFFSET 0
#endif
#if defined(TEST_CBLAS)
/**
* @brief Test tpmv when STORAGE argument is incorrect
* when info == 1
*
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_storage)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( 'x', UPLO, TRANS, DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( 'x', UPLO, TRANS, DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
}
#endif
#if defined(TEST_BLAS_LIKE) || defined(TEST_CBLAS)
/*
Incorrect Input Testing(IIT)
BLAS exceptions get triggered in the following cases (for TPMV):
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 incx == 0 (info = 7)
*/
/**
* @brief Test tpmv when UPLO argument is incorrect
* when info == 1
*
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_UPLO)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, 'A', TRANS, DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, 'A', TRANS, DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
}
/**
* @brief Test tpmv when TRANS argument is incorrect
* when info == 2
*
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_TRANS)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, UPLO, 'A', DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+2 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, UPLO, 'A', DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+2 );
#endif
}
/**
* @brief Test tpmv when DIAG argument is incorrect
* when info == 3
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_DIAG)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, UPLO, TRANS, 'A', N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+3 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, UPLO, TRANS, 'A', N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+3 );
#endif
}
/**
* @brief Test tpmv when N is negative
* when info == 4
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_n)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, -1, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 4 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, -1, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 4 );
#endif
}
/**
* @brief Test tpmv when INCX == 0
* when info == 7
*/
TYPED_TEST(tpmv_IIT_ERS, invalid_incx)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, N, nullptr, nullptr, 0);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 7 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, N, a.data(), x.data(), 0);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 7 );
#endif
}
/*
Early Return Scenarios(ERS) :
The tpmv API is expected to return early in the following cases:
1. When n == 0.
*/
/**
* @brief Test tpmv when N is zero
*/
TYPED_TEST(tpmv_IIT_ERS, n_eq_zero)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, 0, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpmv<T>( STORAGE, UPLO, TRANS, DIAG, 0, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
#endif

View File

@@ -0,0 +1,150 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class ctpmvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( ctpmvGeneric, API )
{
using T = scomplex;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
ctpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<scomplex>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
ctpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incxs
),
::tpmvGenericPrint<scomplex>()
);

View File

@@ -0,0 +1,150 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class dtpmvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( dtpmvGeneric, API )
{
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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
dtpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<double>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
dtpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<double>()
);

View File

@@ -0,0 +1,117 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class dtpmvEVT :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t, // incx
double, // exception value for x
double>> {}; // exception value for A
TEST_P( dtpmvEVT, API )
{
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());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// extreme value for x
double xexval = std::get<6>(GetParam());
// extreme value for A
double aexval = std::get<7>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh, true, xexval, aexval);
}
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
INSTANTIATE_TEST_SUITE_P(
Native,
dtpmvEVT,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'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(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
),
::tpmvEVTPrint<double>()
);

View File

@@ -0,0 +1,150 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class stpmvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( stpmvGeneric, API )
{
using T = float;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
stpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<float>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
stpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<float>()
);

View File

@@ -0,0 +1,203 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "tpmv.h"
#include "level2/ref_tpmv.h"
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include "common/testing_helpers.h"
#include "inc/data_pool.h"
template<typename T>
void test_tpmv(
char storage,
char uploa,
char transa,
char diaga,
gtint_t n,
gtint_t incx,
double thresh,
bool is_evt_test = false,
T evt_x = T{0},
T evt_a = T{0}
)
{
using RT = typename testinghelpers::type_info<T>::real_type;
dim_t len_a = ( n * ( n + 1 ) ) / 2;
//----------------------------------------------------------
// Initialize matrices with random numbers.
//----------------------------------------------------------
// Set index based on n and incx to get varied data
get_pool<T, 0, 1>().set_index(n, incx);
get_pool<T, 1, 3>().set_index(n, incx);
std::vector<T> a = get_pool<T, 0, 1>().get_random_vector(len_a, 1);
// This will use the index from where it was
std::vector<T> x = get_pool<T, 1, 3>().get_random_vector(n, incx);
// Make A matrix diagonal dominant to make sure that algorithm doesn't diverge
// This makes sure that the tpmv problem is solvable
// Packed storage (1-based) accessed as AP(i + j*(j-1)/2) for upper ('U') or AP(i + (2*n - j)*(j-1)/2)
if ( uploa == 'l' || uploa == 'L' )
{
for ( dim_t a_dim = 1; a_dim <= n; ++a_dim )
{
a[ a_dim + (2*n - a_dim)*(a_dim-1)/2 - 1 ] = a[ a_dim + (2*n - a_dim)*(a_dim-1)/2 - 1 ] + T{RT(n)};
}
}
else
{
for ( dim_t a_dim = 1; a_dim <= n; ++a_dim )
{
a[ a_dim + a_dim*(a_dim-1)/2 - 1 ] = a[ a_dim + a_dim*(a_dim-1)/2 - 1 ] + T{RT(n)};
}
}
// add extreme values to the X vector
if ( is_evt_test )
{
x[ (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);
// Change to 1-based indexing
n_idx = n_idx + 1;
m_idx = m_idx + 1;
if ( uploa == 'l' || uploa == 'L' )
{
a[ m_idx + n_idx*(n_idx-1)/2 -1 ] = evt_a;
a[ n_idx + m_idx*(m_idx-1)/2 -1 ] = evt_a;
}
else
{
a[ m_idx + (2*n - n_idx)*(n_idx-1)/2 -1 ] = evt_a;
a[ n_idx + (2*n - m_idx)*(m_idx-1)/2 -1 ] = evt_a;
}
}
// skipped making A triangular
// A matrix being a non triangular matrix could be a better test
// because we are expected 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<T>( storage, uploa, n, a, lda );
// Create a copy of x so that we can check reference results.
std::vector<T> x_ref(x);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
tpmv<T>( storage, uploa, transa, diaga, n, a.data(), x.data(), incx );
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_tpmv<T>( storage, uploa, transa, diaga, n, a.data(), x_ref.data(), incx );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "x", n, x.data(), x_ref.data(), incx, thresh, is_evt_test );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// Test-case logger : Used to print the test-case details based on parameters
template <typename T>
class tpmvGenericPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t>> str) const {
char storage = 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);
gtint_t incx = std::get<5>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_transa_" + std::string(&transa, 1);
str_name += "_diaga_" + std::string(&diaga, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
return str_name;
}
};
template <typename T>
class tpmvEVTPrint
{
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t,T,T>> str) const {
char storage = 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);
gtint_t incx = std::get<5>(str.param);
T xexval = std::get<6>(str.param);
T aexval = std::get<7>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_transa_" + std::string(&transa, 1);
str_name += "_diaga_" + std::string(&diaga, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
str_name = str_name + "_ex_x_" + testinghelpers::get_value_string(xexval);
str_name = str_name + "_ex_a_" + testinghelpers::get_value_string(aexval);
return str_name;
}
};

View File

@@ -0,0 +1,187 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
/**
* @brief Performs the operation
* x := transa(A) * x
* @param[in] storage specifies the form of storage in the memory matrix A
* @param[in] uploa specifies whether the upper or lower triangular part of the array A
* @param[in] transa specifies the form of op( A ) to be used in matrix multiplication
* @param[in] diaga specifies whether the upper or lower triangular part of the array A
* @param[in] n specifies the number of rows of the matrix A
* @param[in] ap specifies pointer which points to the first element of ap
* @param[in,out] xp specifies pointer which points to the first element of xp
* @param[in] incx specifies storage spacing between elements of xp.
*/
template<typename T>
static void tpmv_( char uploa, char transa, char diaga, gtint_t n,
T *ap, T *xp, gtint_t incx )
{
if constexpr (std::is_same<T, float>::value)
stpmv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, double>::value)
dtpmv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, scomplex>::value)
ctpmv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, dcomplex>::value)
ztpmv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: Invalid typename in tpmv_().");
}
template<typename T>
static void tpmv_blis_impl( char uploa, char transa, char diaga, gtint_t n,
T *ap, T *xp, gtint_t incx )
{
if constexpr (std::is_same<T, float>::value)
stpmv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, double>::value)
dtpmv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, scomplex>::value)
ctpmv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, dcomplex>::value)
ztpmv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: Invalid typename in tpmv_blis_impl().");
}
template<typename T>
static void cblas_tpmv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
enum CBLAS_TRANSPOSE cblas_transa;
enum CBLAS_DIAG cblas_diaga;
testinghelpers::char_to_cblas_order( storage, &cblas_order );
testinghelpers::char_to_cblas_uplo( uploa, &cblas_uploa );
testinghelpers::char_to_cblas_trans( transa, &cblas_transa );
testinghelpers::char_to_cblas_diag( diaga, &cblas_diaga );
if constexpr (std::is_same<T, float>::value)
cblas_stpmv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, double>::value)
cblas_dtpmv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, scomplex>::value)
cblas_ctpmv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, dcomplex>::value)
cblas_ztpmv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: Invalid typename in cblas_tpmv().");
}
template<typename T>
static void tpmv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
#if (defined TEST_BLAS_LIKE || defined TEST_CBLAS)
T one;
testinghelpers::initone(one);
#endif
#ifdef TEST_UPPERCASE_ARGS
storage = static_cast<char>(std::toupper(static_cast<unsigned char>(storage)));
uploa = static_cast<char>(std::toupper(static_cast<unsigned char>(uploa)));
transa = static_cast<char>(std::toupper(static_cast<unsigned char>(transa)));
diaga = static_cast<char>(std::toupper(static_cast<unsigned char>(diaga)));
#endif
#ifdef TEST_INPUT_ARGS
// Create copy of scalar input values so we can check that they are not altered.
char storage_cpy = storage;
char uploa_cpy = uploa;
char transa_cpy = transa;
char diaga_cpy = diaga;
gtint_t n_cpy = n;
gtint_t incx_cpy = incx;
// Create copy of input arrays so we can check that they are not altered.
T* ap_cpy = nullptr;
gtint_t size_ap = ( n * ( n + 1 ) ) / 2;
if (ap && size_ap > 0)
{
ap_cpy = new T[size_ap];
memcpy( ap_cpy, ap, size_ap * sizeof( T ) );
}
#endif
#ifdef TEST_BLAS
if(( storage == 'c' || storage == 'C' ))
tpmv_<T>( uploa, transa, diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: BLAS interface cannot be tested for row-major order.");
#elif TEST_BLAS_BLIS_IMPL
if(( storage == 'c' || storage == 'C' ))
tpmv_blis_impl<T>( uploa, transa, diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: BLAS_BLIS_IMPL interface cannot be tested for row-major order.");
#elif TEST_CBLAS
cblas_tpmv<T>( storage, uploa, transa, diaga, n, ap, xp, incx );
#else
throw std::runtime_error("Error in testsuite/level2/tpmv.h: No interfaces are set to be tested.");
#endif
#ifdef TEST_INPUT_ARGS
//----------------------------------------------------------
// Check scalar inputs have not been modified.
//----------------------------------------------------------
computediff<char>( "storage", storage, storage_cpy );
computediff<char>( "uploa", uploa, uploa_cpy );
computediff<char>( "transa", transa, transa_cpy );
computediff<char>( "diaga", diaga, diaga_cpy );
computediff<gtint_t>( "n", n, n_cpy );
computediff<gtint_t>( "incx", incx, incx_cpy );
//----------------------------------------------------------
// Bitwise-wise check array inputs have not been modified.
//----------------------------------------------------------
if (ap && size_ap > 0)
{
computediff<T>( "A", size_ap, ap, ap_cpy, false );
delete[] ap_cpy;
}
#endif
}

View File

@@ -0,0 +1,140 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class ztpmvEVT :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t, // incx
dcomplex, // exception value for x
dcomplex>> {}; // exception value for A
TEST_P( ztpmvEVT, API )
{
using T = dcomplex;
//----------------------------------------------------------
// 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());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// extreme value for x
dcomplex xexval = std::get<6>(GetParam());
// extreme value for A
dcomplex aexval = std::get<7>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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
{
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 1.5;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh, true, xexval, aexval);
}
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
INSTANTIATE_TEST_SUITE_P(
Native,
ztpmvEVT,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'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
::testing::Values(gtint_t(-2), gtint_t(-1),
gtint_t( 1), gtint_t( 2)), // stride size for x
::testing::Values(
dcomplex{AOCL_NAN, 2.1},
dcomplex{2.1, AOCL_NAN},
dcomplex{AOCL_NAN, AOCL_INF},
// dcomplex{2.3, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 2.3}, // fail
// dcomplex{0.0, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 0.0}, // fail
// dcomplex{0.0, -AOCL_INF}, // fail
// dcomplex{-AOCL_INF, 0.0}, // fail
dcomplex{1, 0} ), // exception value for x
::testing::Values(
dcomplex{AOCL_NAN, 3.2},
dcomplex{2.1, AOCL_NAN},
dcomplex{AOCL_NAN, AOCL_INF},
// dcomplex{2.3, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 6.1}, // fail
dcomplex{1, 0}) // exception value for A
),
::tpmvEVTPrint<dcomplex>()
);

View File

@@ -0,0 +1,150 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpmv/test_tpmv.h"
class ztpmvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( ztpmvGeneric, API )
{
using T = dcomplex;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpmv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpmv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
ztpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<dcomplex>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
ztpmvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpmvGenericPrint<dcomplex>()
);

View File

@@ -0,0 +1,297 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 "level2/tpsv/test_tpsv.h"
#include "inc/check_error.h"
#include "common/testing_helpers.h"
#include "common/wrong_inputs_helpers.h"
#include <stdexcept>
#include <algorithm>
#include <gtest/gtest.h>
template <typename T>
class tpsv_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam;
TYPED_TEST_SUITE(tpsv_IIT_ERS, TypeParam);
// Adding namespace to get default parameters(valid case) from testinghelpers/common/wrong_input_helpers.h.
using namespace testinghelpers::IIT;
#if defined(TEST_CBLAS)
#define INFO_OFFSET 1
#else
#define INFO_OFFSET 0
#endif
#if defined(TEST_CBLAS)
/**
* @brief Test tpsv when STORAGE argument is incorrect
* when info == 1
*
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_storage)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( 'x', UPLO, TRANS, DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( 'x', UPLO, TRANS, DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 1 );
#endif
}
#endif
#if defined(TEST_BLAS_LIKE) || defined(TEST_CBLAS)
/*
Incorrect Input Testing(IIT)
BLAS exceptions get triggered in the following cases (for TPSV):
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 incx == 0 (info = 7)
*/
/**
* @brief Test tpsv when UPLO argument is incorrect
* when info == 1
*
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_UPLO)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, 'A', TRANS, DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, 'A', TRANS, DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+1 );
#endif
}
/**
* @brief Test tpsv when TRANS argument is incorrect
* when info == 2
*
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_TRANS)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, UPLO, 'A', DIAG, N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+2 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, UPLO, 'A', DIAG, N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+2 );
#endif
}
/**
* @brief Test tpsv when DIAG argument is incorrect
* when info == 3
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_DIAG)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, UPLO, TRANS, 'A', N, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+3 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, UPLO, TRANS, 'A', N, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, INFO_OFFSET+3 );
#endif
}
/**
* @brief Test tpsv when N is negative
* when info == 4
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_n)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, -1, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 4 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, -1, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 4 );
#endif
}
/**
* @brief Test tpsv when INCX == 0
* when info == 7
*/
TYPED_TEST(tpsv_IIT_ERS, invalid_incx)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, N, nullptr, nullptr, 0);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 7 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, N, a.data(), x.data(), 0);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 7 );
#endif
}
/*
Early Return Scenarios(ERS) :
The tpsv API is expected to return early in the following cases:
1. When n == 0.
*/
/**
* @brief Test tpsv when N is zero
*/
TYPED_TEST(tpsv_IIT_ERS, n_eq_zero)
{
using T = TypeParam;
// Test with nullptr for all suitable arguments that shouldn't be accessed.
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, 0, nullptr, nullptr, INC);
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
// Test with all arguments correct except for the value we are choosing to test.
dim_t len_a = ( N * ( N + 1 ) ) / 2;
std::vector<T> a = testinghelpers::get_random_vector<T>( -2, 5, len_a, 1 );
std::vector<T> x = testinghelpers::get_random_vector<T>(0, 1, N, INC);
std::vector<T> x_ref(x);
tpsv<T>( STORAGE, UPLO, TRANS, DIAG, 0, a.data(), x.data(), INC);
computediff<T>( "x", N, x.data(), x_ref.data(), INC );
#ifdef CAN_TEST_INFO_VALUE
info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
#endif

View File

@@ -0,0 +1,157 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class ctpsvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( ctpsvGeneric, API )
{
using T = scomplex;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 1.5;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
ctpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<scomplex>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
ctpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<scomplex>()
);

View File

@@ -0,0 +1,157 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class dtpsvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( dtpsvGeneric, API )
{
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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 8.1;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
dtpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(33)) // incx
),
::tpsvGenericPrint<double>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
dtpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(33)) // incx
),
::tpsvGenericPrint<double>()
);

View File

@@ -0,0 +1,117 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class dtpsvEVT :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t, // incx
double, // exception value for x
double>> {}; // exception value for A
TEST_P( dtpsvEVT, API )
{
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());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// extreme value for x
double xexval = std::get<6>(GetParam());
// extreme value for A
double aexval = std::get<7>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh, true, xexval, aexval);
}
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
INSTANTIATE_TEST_SUITE_P(
Native,
dtpsvEVT,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'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(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
),
::tpsvEVTPrint<double>()
);

View File

@@ -0,0 +1,157 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class stpsvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( stpsvGeneric, API )
{
using T = float;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 9.0;
#else
double adj = 18.0;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
stpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<float>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
stpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<float>()
);

View File

@@ -0,0 +1,203 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "tpsv.h"
#include "level2/ref_tpsv.h"
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include "common/testing_helpers.h"
#include "inc/data_pool.h"
template<typename T>
void test_tpsv(
char storage,
char uploa,
char transa,
char diaga,
gtint_t n,
gtint_t incx,
double thresh,
bool is_evt_test = false,
T evt_x = T{0},
T evt_a = T{0}
)
{
using RT = typename testinghelpers::type_info<T>::real_type;
dim_t len_a = ( n * ( n + 1 ) ) / 2;
//----------------------------------------------------------
// Initialize matrices with random numbers.
//----------------------------------------------------------
// Set index based on n and incx to get varied data
get_pool<T, 0, 1>().set_index(n, incx);
get_pool<T, 1, 3>().set_index(n, incx);
std::vector<T> a = get_pool<T, 0, 1>().get_random_vector(len_a, 1);
// This will use the index from where it was
std::vector<T> x = get_pool<T, 1, 3>().get_random_vector(n, incx);
// Make A matrix diagonal dominant to make sure that algorithm doesn't diverge
// This makes sure that the tpsv problem is solvable
// Packed storage (1-based) accessed as AP(i + j*(j-1)/2) for upper ('U') or AP(i + (2*n - j)*(j-1)/2)
if ( uploa == 'l' || uploa == 'L' )
{
for ( dim_t a_dim = 1; a_dim <= n; ++a_dim )
{
a[ a_dim + (2*n - a_dim)*(a_dim-1)/2 - 1 ] = a[ a_dim + (2*n - a_dim)*(a_dim-1)/2 - 1 ] + T{RT(n)};
}
}
else
{
for ( dim_t a_dim = 1; a_dim <= n; ++a_dim )
{
a[ a_dim + a_dim*(a_dim-1)/2 - 1 ] = a[ a_dim + a_dim*(a_dim-1)/2 - 1 ] + T{RT(n)};
}
}
// add extreme values to the X vector
if ( is_evt_test )
{
x[ (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);
// Change to 1-based indexing
n_idx = n_idx + 1;
m_idx = m_idx + 1;
if ( uploa == 'l' || uploa == 'L' )
{
a[ m_idx + n_idx*(n_idx-1)/2 -1 ] = evt_a;
a[ n_idx + m_idx*(m_idx-1)/2 -1 ] = evt_a;
}
else
{
a[ m_idx + (2*n - n_idx)*(n_idx-1)/2 -1 ] = evt_a;
a[ n_idx + (2*n - m_idx)*(m_idx-1)/2 -1 ] = evt_a;
}
}
// skipped making A triangular
// A matrix being a non triangular matrix could be a better test
// because we are expected 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<T>( storage, uploa, n, a, lda );
// Create a copy of x so that we can check reference results.
std::vector<T> x_ref(x);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
tpsv<T>( storage, uploa, transa, diaga, n, a.data(), x.data(), incx );
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_tpsv<T>( storage, uploa, transa, diaga, n, a.data(), x_ref.data(), incx );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( "x", n, x.data(), x_ref.data(), incx, thresh, is_evt_test );
#ifdef CAN_TEST_INFO_VALUE
gtint_t info = bli_info_get_info_value();
computediff<gtint_t>( "info", info, 0 );
#endif
}
// Test-case logger : Used to print the test-case details based on parameters
template <typename T>
class tpsvGenericPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t>> str) const {
char storage = 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);
gtint_t incx = std::get<5>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_transa_" + std::string(&transa, 1);
str_name += "_diaga_" + std::string(&diaga, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
return str_name;
}
};
template <typename T>
class tpsvEVTPrint
{
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t,T,T>> str) const {
char storage = 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);
gtint_t incx = std::get<5>(str.param);
T xexval = std::get<6>(str.param);
T aexval = std::get<7>(str.param);
std::string str_name = API_PRINT;
str_name += "_stor_" + std::string(&storage, 1);
str_name += "_uploa_" + std::string(&uploa, 1);
str_name += "_transa_" + std::string(&transa, 1);
str_name += "_diaga_" + std::string(&diaga, 1);
str_name += "_n_" + std::to_string(n);
str_name += "_incx_" + testinghelpers::get_value_string(incx);
str_name = str_name + "_ex_x_" + testinghelpers::get_value_string(xexval);
str_name = str_name + "_ex_a_" + testinghelpers::get_value_string(aexval);
return str_name;
}
};

View File

@@ -0,0 +1,187 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
/**
* @brief Performs the operation:
* x := inv(transa(A)) * x_orig
* @param[in] storage specifies the form of storage in the memory matrix A
* @param[in] uploa specifies whether the upper or lower triangular part of the array A
* @param[in] transa specifies the form of op( A ) to be used in matrix multiplication
* @param[in] diaga specifies whether the upper or lower triangular part of the array A
* @param[in] n specifies the number of rows of the matrix A
* @param[in] ap specifies pointer which points to the first element of ap
* @param[in,out] xp specifies pointer which points to the first element of xp
* @param[in] incx specifies storage spacing between elements of xp.
*/
template<typename T>
static void tpsv_( char uploa, char transa, char diaga, gtint_t n,
T *ap, T *xp, gtint_t incx )
{
if constexpr (std::is_same<T, float>::value)
stpsv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, double>::value)
dtpsv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, scomplex>::value)
ctpsv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, dcomplex>::value)
ztpsv_( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: Invalid typename in tpsv_().");
}
template<typename T>
static void tpsv_blis_impl( char uploa, char transa, char diaga, gtint_t n,
T *ap, T *xp, gtint_t incx )
{
if constexpr (std::is_same<T, float>::value)
stpsv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, double>::value)
dtpsv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, scomplex>::value)
ctpsv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else if constexpr (std::is_same<T, dcomplex>::value)
ztpsv_blis_impl( &uploa, &transa, &diaga, &n, ap, xp, &incx );
else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: Invalid typename in tpsv_blis_impl().");
}
template<typename T>
static void cblas_tpsv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
enum CBLAS_ORDER cblas_order;
enum CBLAS_UPLO cblas_uploa;
enum CBLAS_TRANSPOSE cblas_transa;
enum CBLAS_DIAG cblas_diaga;
testinghelpers::char_to_cblas_order( storage, &cblas_order );
testinghelpers::char_to_cblas_uplo( uploa, &cblas_uploa );
testinghelpers::char_to_cblas_trans( transa, &cblas_transa );
testinghelpers::char_to_cblas_diag( diaga, &cblas_diaga );
if constexpr (std::is_same<T, float>::value)
cblas_stpsv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, double>::value)
cblas_dtpsv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, scomplex>::value)
cblas_ctpsv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else if constexpr (std::is_same<T, dcomplex>::value)
cblas_ztpsv( cblas_order, cblas_uploa, cblas_transa, cblas_diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: Invalid typename in cblas_tpsv().");
}
template<typename T>
static void tpsv( char storage, char uploa, char transa, char diaga,
gtint_t n, T *ap, T *xp, gtint_t incx )
{
#if (defined TEST_BLAS_LIKE || defined TEST_CBLAS)
T one;
testinghelpers::initone(one);
#endif
#ifdef TEST_UPPERCASE_ARGS
storage = static_cast<char>(std::toupper(static_cast<unsigned char>(storage)));
uploa = static_cast<char>(std::toupper(static_cast<unsigned char>(uploa)));
transa = static_cast<char>(std::toupper(static_cast<unsigned char>(transa)));
diaga = static_cast<char>(std::toupper(static_cast<unsigned char>(diaga)));
#endif
#ifdef TEST_INPUT_ARGS
// Create copy of scalar input values so we can check that they are not altered.
char storage_cpy = storage;
char uploa_cpy = uploa;
char transa_cpy = transa;
char diaga_cpy = diaga;
gtint_t n_cpy = n;
gtint_t incx_cpy = incx;
// Create copy of input arrays so we can check that they are not altered.
T* ap_cpy = nullptr;
gtint_t size_ap = ( n * ( n + 1 ) ) / 2;
if (ap && size_ap > 0)
{
ap_cpy = new T[size_ap];
memcpy( ap_cpy, ap, size_ap * sizeof( T ) );
}
#endif
#ifdef TEST_BLAS
if(( storage == 'c' || storage == 'C' ))
tpsv_<T>( uploa, transa, diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: BLAS interface cannot be tested for row-major order.");
#elif TEST_BLAS_BLIS_IMPL
if(( storage == 'c' || storage == 'C' ))
tpsv_blis_impl<T>( uploa, transa, diaga, n, ap, xp, incx );
else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: BLAS_BLIS_IMPL interface cannot be tested for row-major order.");
#elif TEST_CBLAS
cblas_tpsv<T>( storage, uploa, transa, diaga, n, ap, xp, incx );
#else
throw std::runtime_error("Error in testsuite/level2/tpsv.h: No interfaces are set to be tested.");
#endif
#ifdef TEST_INPUT_ARGS
//----------------------------------------------------------
// Check scalar inputs have not been modified.
//----------------------------------------------------------
computediff<char>( "storage", storage, storage_cpy );
computediff<char>( "uploa", uploa, uploa_cpy );
computediff<char>( "transa", transa, transa_cpy );
computediff<char>( "diaga", diaga, diaga_cpy );
computediff<gtint_t>( "n", n, n_cpy );
computediff<gtint_t>( "incx", incx, incx_cpy );
//----------------------------------------------------------
// Bitwise-wise check array inputs have not been modified.
//----------------------------------------------------------
if (ap && size_ap > 0)
{
computediff<T>( "A", size_ap, ap, ap_cpy, false );
delete[] ap_cpy;
}
#endif
}

View File

@@ -0,0 +1,140 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class ztpsvEVT :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t, // incx
dcomplex, // exception value for x
dcomplex>> {}; // exception value for A
TEST_P( ztpsvEVT, API )
{
using T = dcomplex;
//----------------------------------------------------------
// 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());
// stride size for x:
gtint_t incx = std::get<5>(GetParam());
// extreme value for x
dcomplex xexval = std::get<6>(GetParam());
// extreme value for A
dcomplex aexval = std::get<7>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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
{
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 1.5;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh, true, xexval, aexval);
}
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
INSTANTIATE_TEST_SUITE_P(
Native,
ztpsvEVT,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'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
::testing::Values(gtint_t(-2), gtint_t(-1),
gtint_t( 1), gtint_t( 2)), // stride size for x
::testing::Values(
dcomplex{AOCL_NAN, 2.1},
dcomplex{2.1, AOCL_NAN},
dcomplex{AOCL_NAN, AOCL_INF},
// dcomplex{2.3, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 2.3}, // fail
// dcomplex{0.0, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 0.0}, // fail
// dcomplex{0.0, -AOCL_INF}, // fail
// dcomplex{-AOCL_INF, 0.0}, // fail
dcomplex{1, 0} ), // exception value for x
::testing::Values(
dcomplex{AOCL_NAN, 3.2},
dcomplex{2.1, AOCL_NAN},
dcomplex{AOCL_NAN, AOCL_INF},
// dcomplex{2.3, AOCL_INF}, // fail
// dcomplex{AOCL_INF, 6.1}, // fail
dcomplex{1, 0}) // exception value for A
),
::tpsvEVTPrint<dcomplex>()
);

View File

@@ -0,0 +1,157 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2026, 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 <gtest/gtest.h>
#include "level2/tpsv/test_tpsv.h"
class ztpsvGeneric :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // trans
char, // diag
gtint_t, // n
gtint_t // incx
>> {};
TEST_P( ztpsvGeneric, API )
{
using T = dcomplex;
//----------------------------------------------------------
// 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());
// increment for x (incx):
gtint_t incx = std::get<5>(GetParam());
// Set the threshold for the errors:
// Check gtestsuite tpsv.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
{
// Threshold adjustment
#ifdef BLIS_INT_ELEMENT_TYPE
double adj = 1.0;
#else
double adj = 3.1;
#endif
thresh = adj*2*n*testinghelpers::getEpsilon<T>();
}
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
#ifdef OPENMP_NESTED_1diff
#pragma omp parallel default(shared)
{
vary_num_threads();
//std::cout << "Inside 1diff parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#elif OPENMP_NESTED_2
#pragma omp parallel default(shared)
{
#pragma omp parallel default(shared)
{
//std::cout << "Inside 2 parallel regions\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
}
#elif OPENMP_NESTED_1
#pragma omp parallel default(shared)
{
//std::cout << "Inside 1 parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
}
#else
//std::cout << "Not inside parallel region\n";
test_tpsv<T>( storage, uploa, transa, diaga, n, incx, thresh );
#endif
}
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxSmall,
ztpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Range(gtint_t(1),gtint_t(21),1), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<dcomplex>()
);
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
BlackboxMedium,
ztpsvGeneric,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS_LIKE
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uploa
::testing::Values('n','t','c'), // transa
::testing::Values('n','u'), // diaga , n=NONUNIT_DIAG u=UNIT_DIAG
::testing::Values(gtint_t(25),
gtint_t(33),
gtint_t(98),
gtint_t(173),
gtint_t(211)
), // n
::testing::Values(gtint_t(-1),gtint_t(1), gtint_t(7)) // incx
),
::tpsvGenericPrint<dcomplex>()
);

View File

@@ -174,7 +174,7 @@ int computeErrorM(
}
/*
*printing matix and vector
*printing matrix and vector
*
*/