Test-case development for ?OMATCOPY APIs

- Added test-cases to verify the functional behaviour
  of the BLAS-extension API ?omatcopy_(). The test-cases
  cover the following categories for the supported datatypes :
  - Functional and memory testing.
  - Negative parameter testing with invalid inputs.
  - Early return scenarios.
  - Exception value testing.

- Implemented a function to load the reference symbol, based
  on the choice of the reference library. The function definition
  is overloaded due to different API standards being exposed by
  different libraries.

AMD-Internal: [CPUPL-4810][SWLCSG-2706]
Change-Id: I8dcaeeaa36d392b752eb0685e32583a12ddc4220
This commit is contained in:
Vignesh Balasubramanian
2024-03-21 10:59:32 +05:30
parent bd80488af1
commit 70b57cd16f
13 changed files with 2037 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* OMATCOPY performs vector operations
* B := alpha * op(A)
* where A and B are input and output matrices, and alpha is the scaling factor.
* op(A) could be one of the following operations : no-transpose('n'), transpose('t'),
* conjugate('c'), conjugate-transpose('r').
* ==========================================================================
**/
namespace testinghelpers {
template<typename T>
void ref_omatcopy( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,234 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "blis.h"
#include "extension/ref_omatcopy.h"
namespace testinghelpers {
#if defined(REF_IS_OPENBLAS)
// Template function to load and call CBLAS call of OpenBLAS ?omatcopy, only for real datatypes
template<typename T>
void ref_omatcopy_real( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb ) {
// Since CBLAS call does not support plain conjugation, we need to conjugate A
// in case trans == 'r'(only conjugation)
if( trans == 'r' )
{
gtint_t size_a = testinghelpers::matsize(storage, 'n', m, n, lda);
std::vector<T> A_conj( size_a );
memcpy( A_conj.data(), A, size_a * sizeof(T) );
testinghelpers::conj<T>( storage, A_conj.data(), m, n, lda );
memcpy( A, A_conj.data(), size_a * sizeof(T) );
trans = 'n';
}
enum CBLAS_ORDER cblas_order;
enum CBLAS_TRANSPOSE cblas_trans;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_trans( trans, &cblas_trans );
// Defining the function pointer type for CBLAS call of OMATCOPY
typedef void (*Fptr_ref_cblas_omatcopy)(
const CBLAS_ORDER, const CBLAS_TRANSPOSE,
const f77_int, const f77_int, const T,
const T *, const f77_int, const T *,
const f77_int
);
// Function pointer to load the CBLAS symbol
Fptr_ref_cblas_omatcopy ref_cblas_omatcopy = nullptr;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(float))
{
ref_cblas_omatcopy = (Fptr_ref_cblas_omatcopy)refCBLASModule.loadSymbol("cblas_somatcopy");
}
else if (typeid(T) == typeid(double))
{
ref_cblas_omatcopy = (Fptr_ref_cblas_omatcopy)refCBLASModule.loadSymbol("cblas_domatcopy");
}
if (!ref_cblas_omatcopy) {
throw std::runtime_error("Error in ref_omatcopy.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_omatcopy( cblas_order, cblas_trans, m, n, alpha, A, lda, B, ldb );
}
// Template function to load and call CBLAS call of OpenBLAS ?omatcopy, only for complex datatypes
template<typename T>
void ref_omatcopy_complex( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb ) {
// Since CBLAS call does not support plain conjugation, we need to conjugate A
// in case trans == 'r'(only conjugation)
if( trans == 'r' )
{
gtint_t size_a = testinghelpers::matsize(storage, 'n', m, n, lda);
std::vector<T> A_conj( size_a );
memcpy( A_conj.data(), A, size_a * sizeof(T) );
testinghelpers::conj<T>( storage, A_conj.data(), m, n, lda );
memcpy( A, A_conj.data(), size_a * sizeof(T) );
trans = 'n';
}
// Getting the real-precision of the complex datatype
using RT = typename testinghelpers::type_info<T>::real_type;
enum CBLAS_ORDER cblas_order;
enum CBLAS_TRANSPOSE cblas_trans;
char_to_cblas_order( storage, &cblas_order );
char_to_cblas_trans( trans, &cblas_trans );
// Defining the function pointer type for CBLAS call of OMATCOPY
typedef void (*Fptr_ref_cblas_omatcopy)(
const CBLAS_ORDER, const CBLAS_TRANSPOSE,
const f77_int, const f77_int, const RT *,
const RT *, const f77_int, const RT *,
const f77_int
);
// Function pointer to load the CBLAS symbol
Fptr_ref_cblas_omatcopy ref_cblas_omatcopy = nullptr;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(scomplex))
{
ref_cblas_omatcopy = (Fptr_ref_cblas_omatcopy)refCBLASModule.loadSymbol("cblas_comatcopy");
}
else if (typeid(T) == typeid(dcomplex))
{
ref_cblas_omatcopy = (Fptr_ref_cblas_omatcopy)refCBLASModule.loadSymbol("cblas_zomatcopy");
}
if (!ref_cblas_omatcopy) {
throw std::runtime_error("Error in ref_omatcopy.cpp: Function pointer == 0 -- symbol not found.");
}
ref_cblas_omatcopy( cblas_order, cblas_trans, m, n, (RT *)(&alpha), (RT *)A, lda, (RT *)B, ldb );
}
template<typename T>
void ref_omatcopy( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb ) {
// Due to difference in the CBLAS API signature for OpenBLAS ?omatcopy(among real and complex)
// types, we have two different template functions(front-ends), that will be called based on the
// datatype.
if ((typeid(T) == typeid(float)) || (typeid(T) == typeid(double)))
{
ref_omatcopy_real( storage, trans, m, n, alpha, A, lda, B, ldb );
}
else if ((typeid(T) == typeid(scomplex)) || (typeid(T) == typeid(dcomplex)))
{
ref_omatcopy_complex( storage, trans, m, n, alpha, A, lda, B, ldb );
}
else
{
throw std::runtime_error("Error in ref_omatcopy.cpp: Invalid typename is passed function template.");
}
}
#elif defined(REF_IS_MKL)
template<typename T>
void ref_omatcopy( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb ) {
// Defining the function pointer type for the native MKL call of OMATCOPY
typedef void (*Fptr_ref_mkl_omatcopy)(
char, char, size_t, size_t,
const T, const T *, size_t,
T *, size_t
);
// Function pointer to load the MKL symbol
Fptr_ref_mkl_omatcopy ref_mkl_omatcopy = nullptr;
// Call C function
/* Check the typename T passed to this function template and call respective function.*/
if (typeid(T) == typeid(float))
{
ref_mkl_omatcopy = (Fptr_ref_mkl_omatcopy)refCBLASModule.loadSymbol("MKL_Somatcopy");
}
else if (typeid(T) == typeid(double))
{
ref_mkl_omatcopy = (Fptr_ref_mkl_omatcopy)refCBLASModule.loadSymbol("MKL_Domatcopy");
}
else if (typeid(T) == typeid(scomplex))
{
ref_mkl_omatcopy = (Fptr_ref_mkl_omatcopy)refCBLASModule.loadSymbol("MKL_Comatcopy");
}
else if (typeid(T) == typeid(dcomplex))
{
ref_mkl_omatcopy = (Fptr_ref_mkl_omatcopy)refCBLASModule.loadSymbol("MKL_Zomatcopy");
}
else
{
throw std::runtime_error("Error in ref_omatcopy.cpp: Invalid typename is passed function template.");
}
if (!ref_mkl_omatcopy) {
throw std::runtime_error("Error in ref_omatcopy.cpp: Function pointer == 0 -- symbol not found.");
}
ref_mkl_omatcopy( storage, trans, m, n, alpha, A, lda, B, ldb );
}
#else
template<typename T>
void ref_omatcopy( char storage, char trans, gtint_t m, gtint_t n, T alpha, T* A,
gtint_t lda, T* B, gtint_t ldb ) {
throw std::runtime_error("Error in ref_omatcopy.cpp: The provided reference does not support the required operation.");
}
#endif
// Explicit template instantiations
#if defined(REF_IS_OPENBLAS)
template void ref_omatcopy_real<float>( char, char, gtint_t, gtint_t, float, float*, gtint_t, float*, gtint_t );
template void ref_omatcopy_real<double>( char, char, gtint_t, gtint_t, double, double*, gtint_t, double*, gtint_t );
template void ref_omatcopy_complex<scomplex>( char, char, gtint_t, gtint_t, scomplex, scomplex*, gtint_t, scomplex*, gtint_t );
template void ref_omatcopy_complex<dcomplex>( char, char, gtint_t, gtint_t, dcomplex, dcomplex*, gtint_t, dcomplex*, gtint_t );
#endif
template void ref_omatcopy<float>( char, char, gtint_t, gtint_t, float, float*, gtint_t, float*, gtint_t );
template void ref_omatcopy<double>( char, char, gtint_t, gtint_t, double, double*, gtint_t, double*, gtint_t );
template void ref_omatcopy<scomplex>( char, char, gtint_t, gtint_t, scomplex, scomplex*, gtint_t, scomplex*, gtint_t );
template void ref_omatcopy<dcomplex>( char, char, gtint_t, gtint_t, dcomplex, dcomplex*, gtint_t, dcomplex*, gtint_t );
} //end of namespace testinghelpers

View File

@@ -0,0 +1,176 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class comatcopyEVT :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
scomplex, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
scomplex, // exval
bool>> {}; // is_nan_inf_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(comatcopyEVT);
// Tests using random numbers as vector elements.
TEST_P( comatcopyEVT, NanInfCheck )
{
using T = scomplex;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// exval
T exval = std::get<7>(GetParam());
// is_nan_inf_test
bool is_nan_inf_test = std::get<8>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) && !(std::isnan(alpha.real) || std::isnan(alpha.imag)) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
// Note: is_memory_test is passed as false(hard-coded), since memory tests are done in _generic.cpp files
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, false, is_nan_inf_test, exval );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class comatcopyEVTPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,scomplex,gtint_t,gtint_t,scomplex,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
scomplex alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
scomplex exval = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
str_name = str_name + "_alpha_exval" + testinghelpers::get_value_string(alpha);
str_name = str_name + "_A_exval" + testinghelpers::get_value_string(exval);
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
return str_name;
}
};
static float AOCL_NAN = std::numeric_limits<float>::quiet_NaN();
static float AOCL_INF = std::numeric_limits<float>::infinity();
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// EVT testing for comatcopy, with exception values in A matrix
INSTANTIATE_TEST_SUITE_P(
matrixA,
comatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(scomplex{2.3, -3.5}, scomplex{1.0, 0.0},
scomplex{0.0, 0.0}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(scomplex{AOCL_INF, 0.0}, scomplex{0.0, -AOCL_INF},
scomplex{0.0, AOCL_NAN}, scomplex{AOCL_NAN, AOCL_INF}), // exval
::testing::Values(true) // is_nan_inf_test
),
::comatcopyEVTPrint()
);
// EVT testing for comatcopy, with exception values in alpha
INSTANTIATE_TEST_SUITE_P(
alpha,
comatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(scomplex{AOCL_INF, 0.0}, scomplex{0.0, -AOCL_INF},
scomplex{0.0, AOCL_NAN}, scomplex{AOCL_NAN, AOCL_INF}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(scomplex{0.0, 0.0}), // exval
::testing::Values(true) // is_nan_inf_test
),
::comatcopyEVTPrint()
);
#endif

View File

@@ -0,0 +1,148 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class comatcopyAPI :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
scomplex, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
bool>> {}; // is_memory_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(comatcopyAPI);
// Tests using random numbers as vector elements.
TEST_P( comatcopyAPI, FunctionalTest )
{
using T = scomplex;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// is_memory_test
bool is_memory_test = std::get<7>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, is_memory_test );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class comatcopyAPIPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,scomplex,gtint_t,gtint_t,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
scomplex alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
bool is_memory_test = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
std::string alpha_str = ( alpha.real >= 0) ? std::to_string(int(alpha.real)) : ("m" + std::to_string(int(std::abs(alpha.real))));
alpha_str += "pi" + (( alpha.imag >= 0) ? std::to_string(int(alpha.imag)) : ("m" + std::to_string(int(std::abs(alpha.imag)))));
str_name = str_name + "_a" + alpha_str;
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
str_name += ( is_memory_test )? "_mem_test_enabled" : "_mem_test_disabled";
return str_name;
}
};
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// Black box testing for generic and main use of comatcopy.
INSTANTIATE_TEST_SUITE_P(
Blackbox,
comatcopyAPI,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(scomplex{2.3, -3.5}, scomplex{-3.1, 1.7},
scomplex{1.0, 0.0}, scomplex{0.0, 0.0}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(false, true) // is_memory_test
),
::comatcopyAPIPrint()
);
#endif

View File

@@ -0,0 +1,173 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class domatcopyEVT :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
double, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
double, // exval
bool>> {}; // is_nan_inf_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(domatcopyEVT);
// Tests using random numbers as vector elements.
TEST_P( domatcopyEVT, NanInfCheck )
{
using T = double;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// exval
T exval = std::get<7>(GetParam());
// is_nan_inf_test
bool is_nan_inf_test = std::get<8>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) && !(std::isnan(alpha)) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
// Note: is_memory_test is passed as false(hard-coded), since memory tests are done in _generic.cpp files
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, false, is_nan_inf_test, exval );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class domatcopyEVTPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,double,gtint_t,gtint_t,double,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
double alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
double exval = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
str_name = str_name + "_alpha_exval" + testinghelpers::get_value_string(alpha);
str_name = str_name + "_A_exval" + testinghelpers::get_value_string(exval);
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
return str_name;
}
};
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// EVT testing for domatcopy, with exception values in A matrix
INSTANTIATE_TEST_SUITE_P(
matrixA,
domatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(2.0, -3.0, 1.0, 0.0), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(AOCL_NAN, AOCL_INF, -AOCL_INF), // exval
::testing::Values(true) // is_nan_inf_test
),
::domatcopyEVTPrint()
);
// EVT testing for domatcopy, with exception values in alpha
INSTANTIATE_TEST_SUITE_P(
alpha,
domatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(AOCL_NAN, AOCL_INF, -AOCL_INF), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(0.0), // exval
::testing::Values(true) // is_nan_inf_test
),
::domatcopyEVTPrint()
);
#endif

View File

@@ -0,0 +1,146 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class domatcopyAPI :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
double, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
bool>> {}; // is_memory_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(domatcopyAPI);
// Tests using random numbers as vector elements.
TEST_P( domatcopyAPI, FunctionalTest )
{
using T = double;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// is_memory_test
bool is_memory_test = std::get<7>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, is_memory_test );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class domatcopyAPIPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,double,gtint_t,gtint_t,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
float alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
bool is_memory_test = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
std::string alpha_str = ( alpha >= 0) ? std::to_string(int(alpha)) : ("m" + std::to_string(int(std::abs(alpha))));
str_name = str_name + "_a" + alpha_str;
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
str_name += ( is_memory_test )? "_mem_test_enabled" : "_mem_test_disabled";
return str_name;
}
};
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// Black box testing for generic and main use of domatcopy.
INSTANTIATE_TEST_SUITE_P(
Blackbox,
domatcopyAPI,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(2.0, -3.0, 1.0, 0.0), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(false, true) // is_memory_test
),
::domatcopyAPIPrint()
);
#endif

View File

@@ -0,0 +1,77 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
/**
* @brief Performs the operation:
* B := alpha * op(A),
* where op(A) could be A, A(transpose), A(conjugate), A(conjugate-transpose)
* @param[in] m number of rows in A, number of rows/columns in B
* @param[in] n number of columns in A, number of columns/rows in B
* @param[in] alpha scalar
* @param[in] A pointer which points to the first element of A matrix
* @param[in] lda leading dimension of A matrix
* @param[in, out] B pointer which points to the first element of B matrix
* @param[in] ldb leading dimension of B matrix
*/
template<typename T>
static void omatcopy_( char trans, gtint_t m, gtint_t n, T alpha, T* A, gtint_t lda, T* B, gtint_t ldb )
{
if constexpr (std::is_same<T, float>::value)
somatcopy_( &trans, &m, &n, (const float *)&alpha, A, &lda, B, &ldb );
else if constexpr (std::is_same<T, double>::value)
domatcopy_( &trans, &m, &n, (const double *)&alpha, A, &lda, B, &ldb );
else if constexpr (std::is_same<T, scomplex>::value)
comatcopy_( &trans, &m, &n, (const scomplex *)&alpha, A, &lda, B, &ldb );
else if constexpr (std::is_same<T, dcomplex>::value)
zomatcopy_( &trans, &m, &n, (const dcomplex *)&alpha, A, &lda, B, &ldb );
else
throw std::runtime_error("Error in testsuite/level1/omatcopy.h: Invalid typename in omatcopy_().");
}
template<typename T>
static void omatcopy( char trans, gtint_t m, gtint_t n, T alpha, T* A, gtint_t lda, T* B, gtint_t ldb )
{
#ifdef TEST_BLAS
omatcopy_<T>( trans, m, n, alpha, A, lda, B, ldb );
#else
throw std::runtime_error("Error in testsuite/level1/omatcopy.h: No interfaces are set to be tested.");
#endif
}

View File

@@ -0,0 +1,241 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
#include "common/wrong_inputs_helpers.h"
#include "common/testing_helpers.h"
#include "inc/check_error.h"
template <typename T>
class omatcopy_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam;
TYPED_TEST_SUITE(omatcopy_IIT_ERS, TypeParam);
using namespace testinghelpers::IIT;
#if defined(TEST_BLAS)
/*
Incorrect Input Testing(IIT)
The exceptions get triggered in the following cases:
1. When TRANS != 'n' || TRANS != 't' || TRANS != 'c' || TRANS != 'r'
2. When m < 0
3. When n < 0
4. When lda < max(1, m).
5. When ldb < max(1, thresh), thresh set based on TRANS value
*/
// When TRANS is invalid
TYPED_TEST(omatcopy_IIT_ERS, invalid_transa)
{
using T = TypeParam;
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDA );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDB );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid value for TRANS value for the operation.
omatcopy<T>( 'Q', M, N, alpha, A.data(), LDA, B.data(), LDB);
// Use bitwise comparison (no threshold).
computediff<T>( 'c', M, N, B.data(), B_ref.data(), LDB );
}
// When m < 0
TYPED_TEST(omatcopy_IIT_ERS, m_lt_zero)
{
using T = TypeParam;
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDA );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDB );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid m for the operation.
omatcopy<T>( TRANS, -1, N, alpha, A.data(), LDA, B.data(), LDB);
// Use bitwise comparison (no threshold).
computediff<T>( 'c', M, N, B.data(), B_ref.data(), LDB );
}
// When n < 0
TYPED_TEST(omatcopy_IIT_ERS, n_lt_zero)
{
using T = TypeParam;
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDA );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', M, N, LDB );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid n for the operation.
omatcopy<T>( TRANS, M, -1, alpha, A.data(), LDA, B.data(), LDB);
// Use bitwise comparison (no threshold).
computediff<T>( 'c', M, N, B.data(), B_ref.data(), LDB );
}
// When lda < m
TYPED_TEST(omatcopy_IIT_ERS, invalid_lda)
{
using T = TypeParam;
// Having different values for m and n
gtint_t m = 5;
gtint_t n = 10;
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid lda for the operation.
omatcopy<T>( 'n', m, n, alpha, A.data(), m - 1, B.data(), m);
// Use bitwise comparison (no threshold).
computediff<T>( 'c', m, n, B.data(), B_ref.data(), m );
}
// When ldb < m, with trans == 'n'
TYPED_TEST(omatcopy_IIT_ERS, invalid_ldb_no_transpose)
{
using T = TypeParam;
// Having different values for m and n
gtint_t m = 5;
gtint_t n = 10;
char trans = 'n';
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid ldb for the operation.
omatcopy<T>( trans, m, n, alpha, A.data(), m - 1, B.data(), m );
// Use bitwise comparison (no threshold).
computediff<T>( 'c', m, n, B.data(), B_ref.data(), m );
}
// When ldb < m, with trans == 'r'
TYPED_TEST(omatcopy_IIT_ERS, invalid_ldb_conjugate)
{
using T = TypeParam;
// Having different values for m and n
gtint_t m = 5;
gtint_t n = 10;
char trans = 'r';
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid ldb for the operation.
omatcopy<T>( trans, m, n, alpha, A.data(), m, B.data(), m - 1 );
// Use bitwise comparison (no threshold).
computediff<T>( 'c', m, n, B.data(), B_ref.data(), m );
}
// When ldb < m, with trans == 't'
TYPED_TEST(omatcopy_IIT_ERS, invalid_ldb_transpose)
{
using T = TypeParam;
// Having different values for m and n
gtint_t m = 5;
gtint_t n = 10;
char trans = 't';
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 't', m, n, n );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid ldb for the operation.
omatcopy<T>( trans, m, n, alpha, A.data(), m, B.data(), n - 1 );
// Use bitwise comparison (no threshold).
computediff<T>( 'c', n, m, B.data(), B_ref.data(), n );
}
// When ldb < m, with trans == 'c'
TYPED_TEST(omatcopy_IIT_ERS, invalid_ldb_conjugate_transpose)
{
using T = TypeParam;
// Having different values for m and n
gtint_t m = 5;
gtint_t n = 10;
char trans = 'c';
// Defining the A and B matrices with values for debugging purposes
std::vector<T> A = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 'n', m, n, m );
std::vector<T> B = testinghelpers::get_random_matrix<T>(-10, 10, 'c', 't', m, n, n );
// Copy so that we check that the elements of B are not modified.
std::vector<T> B_ref(B);
T alpha;
testinghelpers::initone<T>( alpha );
// Call OMATCOPY with a invalid ldb for the operation.
omatcopy<T>( trans, m, n, alpha, A.data(), m, B.data(), n - 1 );
// Use bitwise comparison (no threshold).
computediff<T>( 'c', n, m, B.data(), B_ref.data(), n );
}
#endif

View File

@@ -0,0 +1,173 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class somatcopyEVT :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
float, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
float, // exval
bool>> {}; // is_nan_inf_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(somatcopyEVT);
// Tests using random numbers as vector elements.
TEST_P( somatcopyEVT, NanInfCheck )
{
using T = float;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// exval
T exval = std::get<7>(GetParam());
// is_nan_inf_test
bool is_nan_inf_test = std::get<8>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) && !(std::isnan(alpha)) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
// Note: is_memory_test is passed as false(hard-coded), since memory tests are done in _generic.cpp files
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, false, is_nan_inf_test, exval );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class somatcopyEVTPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,float,gtint_t,gtint_t,float,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
float alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
float exval = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
str_name = str_name + "_alpha_exval" + testinghelpers::get_value_string(alpha);
str_name = str_name + "_A_exval" + testinghelpers::get_value_string(exval);
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
return str_name;
}
};
static float AOCL_NAN = std::numeric_limits<float>::quiet_NaN();
static float AOCL_INF = std::numeric_limits<float>::infinity();
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// EVT testing for somatcopy, with exception values in A matrix
INSTANTIATE_TEST_SUITE_P(
matrixA,
somatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(2.0f, -3.0f, 1.0f, 0.0f), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(AOCL_NAN, AOCL_INF, -AOCL_INF), // exval
::testing::Values(true) // is_nan_inf_test
),
::somatcopyEVTPrint()
);
// EVT testing for somatcopy, with exception values in alpha
INSTANTIATE_TEST_SUITE_P(
alpha,
somatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(AOCL_NAN, AOCL_INF, -AOCL_INF), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(0.0f), // exval
::testing::Values(true) // is_nan_inf_test
),
::somatcopyEVTPrint()
);
#endif

View File

@@ -0,0 +1,146 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class somatcopyAPI :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
float, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
bool>> {}; // is_memory_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(somatcopyAPI);
// Tests using random numbers as vector elements.
TEST_P( somatcopyAPI, FunctionalTest )
{
using T = float;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// is_memory_test
bool is_memory_test = std::get<7>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, is_memory_test );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class somatcopyAPIPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,float,gtint_t,gtint_t,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
float alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
bool is_memory_test = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
std::string alpha_str = ( alpha >= 0) ? std::to_string(int(alpha)) : ("m" + std::to_string(int(std::abs(alpha))));
str_name = str_name + "_a" + alpha_str;
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
str_name += ( is_memory_test )? "_mem_test_enabled" : "_mem_test_disabled";
return str_name;
}
};
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// Black box testing for generic and main use of somatcopy.
INSTANTIATE_TEST_SUITE_P(
Blackbox,
somatcopyAPI,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(2.0f, -3.0f, 1.0f, 0.0f), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(false, true) // is_memory_test
),
::somatcopyAPIPrint()
);
#endif

View File

@@ -0,0 +1,144 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "omatcopy.h"
#include "extension/ref_omatcopy.h"
#include "inc/check_error.h"
#include<cstdlib>
/**
* @brief Generic test body for omatcopy operation.
*/
template<typename T>
static void test_omatcopy( char storage, char trans, gtint_t m, gtint_t n, T alpha, gtint_t lda_inc, gtint_t ldb_inc,
double thresh, bool is_memory_test = false, bool is_nan_inf_test = false, T exval = T{0.0} )
{
// Set an alternative trans value that corresponds to only
// whether the B matrix should be mxn or nxm(only transposing)
char B_trans;
B_trans = ( ( trans == 'n' ) || ( trans == 'r' ) )? 'n' : 't';
// Compute the leading dimensions of A and B.
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, B_trans, m, n, ldb_inc );
// Compute sizes of A and B, in bytes
gtint_t size_a = testinghelpers::matsize( storage, 'n', m, n, lda ) * sizeof( T );
gtint_t size_b = testinghelpers::matsize( storage, B_trans, m, n, ldb ) * sizeof( T );
// Create the objects for the input and output operands
// The API does not expect the memory to be aligned
testinghelpers::ProtectedBuffer A_buf( size_a, false, is_memory_test );
testinghelpers::ProtectedBuffer B_buf( size_b, false, is_memory_test );
testinghelpers::ProtectedBuffer B_ref_buf( size_b, false, false );
// Pointers to access the memory chunks
T *A, *B, *B_ref;
// Acquire the first set of greenzones for A and B
A = ( T* )A_buf.greenzone_1;
B = ( T* )B_buf.greenzone_1;
B_ref = ( T* )B_ref_buf.greenzone_1; // For B_ref, there is no greenzone_2
// Initiaize the memory with random data
testinghelpers::datagenerators::randomgenerators( -10, 10, storage, m, n, A, 'n', lda );
testinghelpers::datagenerators::randomgenerators( -10, 10, storage, m, n, B, B_trans, ldb );
if( is_nan_inf_test )
{
gtint_t rand_m = rand() % m;
gtint_t rand_n = rand() % n;
gtint_t idx = ( storage == 'c' || storage == 'C' )? ( rand_m + rand_n * lda ) : ( rand_n + rand_m * lda );
A[idx] = exval;
}
// Copying the contents of B to B_ref
memcpy( B_ref, B, size_b );
// Add signal handler for segmentation fault
testinghelpers::ProtectedBuffer::start_signal_handler();
try
{
// Call the API.
// This call is made irrespective of is_memory_test.
// This will check for out of bounds access with first redzone(if memory test is true)
// Else, it will just call the ukr function.
omatcopy<T>( trans, m, n, alpha, A, lda, B, ldb);
if ( is_memory_test )
{
// Acquire the pointers near the second redzone
A = ( T* )A_buf.greenzone_2;
B = ( T* )B_buf.greenzone_2;
// Copy the data for A and B accordingly
// NOTE : The objects for A and B will have acquired enough memory
// such that the greenzones in each do not overlap.
memcpy( A, A_buf.greenzone_1, size_a );
memcpy( B, B_buf.greenzone_1, size_b );
// Call the API, to check with the second redzone.
omatcopy<T>( trans, m, n, alpha, A, lda, B, ldb);
}
}
catch(const std::exception& e)
{
// Reset to default signal handler
testinghelpers::ProtectedBuffer::stop_signal_handler();
// Show failure in case seg fault was detected
FAIL() << "Memory Test Failed";
}
// Reset to default signal handler
testinghelpers::ProtectedBuffer::stop_signal_handler();
//----------------------------------------------------------
// Call reference implementation to get ref results.
//----------------------------------------------------------
testinghelpers::ref_omatcopy( storage, trans, m, n, alpha, A, lda, B_ref, ldb );
//----------------------------------------------------------
// Compute component-wise error.
//----------------------------------------------------------
if( B_trans == 'n' )
computediff<T>( storage, m, n, B, B_ref, ldb, thresh, is_nan_inf_test );
else
computediff<T>( storage, n, m, B, B_ref, ldb, thresh, is_nan_inf_test );
}

View File

@@ -0,0 +1,176 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class zomatcopyEVT :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
dcomplex, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
dcomplex, // exval
bool>> {}; // is_nan_inf_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(zomatcopyEVT);
// Tests using random numbers as vector elements.
TEST_P( zomatcopyEVT, NanInfCheck )
{
using T = dcomplex;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// exval
T exval = std::get<7>(GetParam());
// is_nan_inf_test
bool is_nan_inf_test = std::get<8>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) && !(std::isnan(alpha.real) || std::isnan(alpha.imag)) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
// Note: is_memory_test is passed as false(hard-coded), since memory tests are done in _generic.cpp files
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, false, is_nan_inf_test, exval );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class zomatcopyEVTPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,dcomplex,gtint_t,gtint_t,dcomplex,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
dcomplex alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
dcomplex exval = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
str_name = str_name + "_alpha_exval" + testinghelpers::get_value_string(alpha);
str_name = str_name + "_A_exval" + testinghelpers::get_value_string(exval);
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
return str_name;
}
};
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// EVT testing for zomatcopy, with exception values in A matrix
INSTANTIATE_TEST_SUITE_P(
matrixA,
zomatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(dcomplex{2.3, -3.5}, dcomplex{1.0, 0.0},
dcomplex{0.0, 0.0}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(dcomplex{AOCL_INF, 0.0}, dcomplex{0.0, -AOCL_INF},
dcomplex{0.0, AOCL_NAN}, dcomplex{AOCL_NAN, AOCL_INF}), // exval
::testing::Values(true) // is_nan_inf_test
),
::zomatcopyEVTPrint()
);
// EVT testing for zomatcopy, with exception values in alpha
INSTANTIATE_TEST_SUITE_P(
alpha,
zomatcopyEVT,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(dcomplex{AOCL_INF, 0.0}, dcomplex{0.0, -AOCL_INF},
dcomplex{0.0, AOCL_NAN}, dcomplex{AOCL_NAN, AOCL_INF}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(dcomplex{0.0, 0.0}), // exval
::testing::Values(true) // is_nan_inf_test
),
::zomatcopyEVTPrint()
);
#endif

View File

@@ -0,0 +1,148 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_omatcopy.h"
class zomatcopyAPI :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // trans
gtint_t, // m
gtint_t, // n
dcomplex, // alpha
gtint_t, // lda_inc
gtint_t, // ldb_inc
bool>> {}; // is_memory_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(zomatcopyAPI);
// Tests using random numbers as vector elements.
TEST_P( zomatcopyAPI, FunctionalTest )
{
using T = dcomplex;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes the storage format of the input matrices
char storage = std::get<0>(GetParam());
// denotes the trans value for the operation
char trans = std::get<1>(GetParam());
// m dimension
gtint_t m = std::get<2>(GetParam());
// n dimension
gtint_t n = std::get<3>(GetParam());
// alpha
T alpha = std::get<4>(GetParam());
// lda_inc for A
gtint_t lda_inc = std::get<5>(GetParam());
// ldb_inc for B
gtint_t ldb_inc = std::get<6>(GetParam());
// is_memory_test
bool is_memory_test = std::get<7>(GetParam());
double thresh = 0.0;
// Set the threshold for the errors
if( ( alpha != testinghelpers::ZERO<T>() || alpha != testinghelpers::ONE<T>() ) )
thresh = 3 * testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_omatcopy<T>( storage, trans, m, n, alpha, lda_inc, ldb_inc, thresh, is_memory_test );
}
// Test-case logger : Used to print the test-case details based on parameters
// The string format is as follows :
// {blas_/cblas_/bli_}_storage_trans_m_n_alpha_lda_ldb_{mem_test_enabled/mem_test_disabled}
class zomatcopyAPIPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,gtint_t,gtint_t,dcomplex,gtint_t,gtint_t,bool>> str) const {
char storage = std::get<0>(str.param);
char trans = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
dcomplex alpha = std::get<4>(str.param);
gtint_t lda_inc = std::get<5>(str.param);
gtint_t ldb_inc = std::get<6>(str.param);
bool is_memory_test = std::get<7>(str.param);
// Currently, BLIS only has the BLAS standard wrapper for this API.
// The CBLAS and BLIS strings are also added here(with macro guards),
// in case we add the CBLAS and BLIS wrappers to the library in future.
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name += std::string(&storage, 1);
str_name += "_" + std::string(&trans, 1);
str_name += "_" + std::to_string(m);
str_name += "_" + std::to_string(n);
std::string alpha_str = ( alpha.real >= 0) ? std::to_string(int(alpha.real)) : ("m" + std::to_string(int(std::abs(alpha.real))));
alpha_str += "pi" + (( alpha.imag >= 0) ? std::to_string(int(alpha.imag)) : ("m" + std::to_string(int(std::abs(alpha.imag)))));
str_name = str_name + "_a" + alpha_str;
gtint_t lda = testinghelpers::get_leading_dimension( storage, 'n', m, n, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trans, m, n, ldb_inc );
str_name += "_lda" + std::to_string(lda);
str_name += "_ldb" + std::to_string(ldb);
str_name += ( is_memory_test )? "_mem_test_enabled" : "_mem_test_disabled";
return str_name;
}
};
#if defined(TEST_BLAS) && (defined(REF_IS_MKL) || defined(REF_IS_OPENBLAS))
// Black box testing for generic and main use of zomatcopy.
INSTANTIATE_TEST_SUITE_P(
Blackbox,
zomatcopyAPI,
::testing::Combine(
::testing::Values('c'), // storage format(currently only for BLAS testing)
::testing::Values('n', 't', 'r', 'c'), // trans(and/or conj) value
// 'n' - no-transpose, 't' - transpose
// 'r' - conjugate, 'c' - conjugate-transpose
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // m
::testing::Values(gtint_t(10), gtint_t(55), gtint_t(243)), // n
::testing::Values(dcomplex{2.3, -3.5}, dcomplex{-3.1, 1.7},
dcomplex{1.0, 0.0}, dcomplex{0.0, 0.0}), // alpha
::testing::Values(gtint_t(0), gtint_t(25)), // increment of lda
::testing::Values(gtint_t(0), gtint_t(17)), // increment of ldb
::testing::Values(false, true) // is_memory_test
),
::zomatcopyAPIPrint()
);
#endif