Gtestsuite: Added overflow and underflow tests for dgemm

- Added overflow and underflow tests for dgemm

  These tests cause floating point overflow and underflow by feeding
  values close to DBL_MAX and DBL_MIN values to matrices
  DBL_MAX = 1.7976931348623158e+308
  DBL_MIN = 2.2250738585072014e-308

  When computations result in values beyond the range [DBL_MIN, DBL_MAX],
  it leads to an overflow or underflow condition

  Two new arguments are added to test_gemm routine - over_under and input_range

  over_under = 0 indicates overflow
  over_under = 1 indicates underflow

  input_range = -1 indicates values within overflow or underflow limits
  input_range = 0  indicates values very close to DBL_MIN or DBL_MAX
  input_range = 1  indicates values beyond DBL_MIN or DBL_MAX

- New file: dgemm_ovr_undr.cpp

  Overflow and underflow tests are called from this file
  dgemm_overflow and dgemm_underflow. This file uses
  cfloat header file for DBL_MIN and DBL_MAX values

Signed-off-by: Nimmy Krishnan <nimmy.krishnan@amd.com>
AMD-Internal: [CPUPL-4492]
Change-Id: I4bbd519abacc56f322c73d6c0187ed6e1abbbf2b
This commit is contained in:
Nimmy Krishnan
2024-02-06 08:25:54 +00:00
parent 70b57cd16f
commit 9226641585
3 changed files with 685 additions and 5 deletions

View File

@@ -33,6 +33,7 @@
*/
#include <random>
#include <type_traits>
#include "common/testing_helpers.h"
namespace testinghelpers {
@@ -114,7 +115,7 @@ void getfp(T2 from, T3 to, gtint_t n, gtint_t incx, T1* x)
* with elements that follow a uniform distribution in the range [from, to].
* @param[in] storage storage type of matrix A, row or column major
* @param[in] m, n dimentions of matrix A
* @param[in, out] a the random fp matrix A
* @param[in, out] a the random fp matrix A
* @param[in] lda leading dimension of matrix A
*/
template<typename T1, typename T2, typename T3>
@@ -177,7 +178,7 @@ void getfp(T2 from, T3 to, char storage, gtint_t m, gtint_t n, T1* a, gtint_t ld
* @brief Returns a random fp vector (float, double, scomplex, dcomplex)
* with elements that follow a uniform distribution in the range [from, to].
* @param[in] storage storage type of matrix A, row or column major
* @param[in] m, n dimentions of matrix A
* @param[in] m, n dimentions of matrix A
* @param[in, out] a the random fp matrix A
* @param[in] trans transposition of matrix A
* @param[in] lda leading dimension of matrix A
@@ -254,7 +255,7 @@ void getint(int from, int to, gtint_t n, gtint_t incx, T* x)
* with elements that are integers and follow a uniform distribution in the range [from, to].
* @param[in] storage storage type of matrix A, row or column major
* @param[in] m, n dimentions of matrix A
* @param[in, out] a the random fp matrix A
* @param[in, out] a the random fp matrix A
* @param[in] lda leading dimension of matrix A
*/
template<typename T>
@@ -318,7 +319,7 @@ void getint(int from, int to, char storage, gtint_t m, gtint_t n, T* a, gtint_t
* @brief Returns a random fp matrix (float, double, scomplex, dcomplex)
* with elements that are integers and follow a uniform distribution in the range [from, to].
* @param[in] storage storage type of matrix A, row or column major
* @param[in] m, n dimentions of matrix A
* @param[in] m, n dimentions of matrix A
* @param[in, out] a the random fp matrix A
* @param[in] trans transposition of matrix A
* @param[in] lda leading dimension of matrix A
@@ -531,4 +532,96 @@ void set_ev_mat( char storage, char trns, gtint_t ld, gtint_t i, gtint_t j, T ex
}
}
/*
Function to set few values of a matrix to values relative to DBL_MAX/DBL_MIN
These values are used to create overflow and underflow scenarios
*/
template<typename T>
void set_overflow_underflow_mat(char storage, char trns, gtint_t ld, gtint_t i, gtint_t j, T* a, gtint_t mode, gtint_t input_range)
{
/* Calculate index where overflow/underflow values need to be inserted */
gtint_t indexA = 0;
if ( storage == 'c' || storage == 'C' )
{
if ( trns == 'n' || trns == 'N' )
{
indexA = i + j*ld;
}
else
{
indexA = j + i*ld;
}
}
else
{
if ( trns == 'n' || trns == 'N' )
{
indexA = i*ld + j;
}
else
{
indexA = j*ld + i;
}
}
using RT = typename testinghelpers::type_info<T>::real_type;
std::vector<int> exponent(12);
if (std::is_same<RT, double>::value)
{
exponent = {23, 203, 18, 180, 123, 130, 185, 178, 108, 158, 185, 220};
}
else if (std::is_same<RT, float>::value)
{
exponent = {3, 20, 8, 2, 30, 28, 8, 10, 33, 24, 8, 22};
}
T limits_val;
/* When mode is set to 0, values relative to DBL_MAX are inserted into the input matrices */
if(mode == 0)
{
limits_val = (std::numeric_limits<RT>::max)();
switch(input_range)
{
case -1:
a[0] = limits_val/ pow(10, exponent[0]);
a[indexA] = limits_val/ pow(10, exponent[1]);
break;
case 0:
a[0] = -(limits_val/ pow(10, exponent[4]));
a[indexA] = -(limits_val/ pow(10, exponent[5]));
break;
case 1:
a[0] = limits_val/ pow(10, exponent[8]);
a[indexA] = limits_val/ pow(10, exponent[9]);
}
}
/* When mode is set to 1, values relative to DBL_MIN are inserted into the input matrices*/
else
{
limits_val = (std::numeric_limits<RT>::min)();
switch(input_range)
{
case -1:
a[0] = limits_val * pow(10, exponent[0]);
a[indexA] = limits_val * pow(10, exponent[1]);
break;
case 0:
a[0] = -(limits_val * pow(10, exponent[4]));
a[indexA] = -(limits_val * pow(10, exponent[5]));
break;
case 1:
a[0] = limits_val * pow(10, exponent[8]);
a[indexA] = limits_val * pow(10, exponent[9]);
}
}
}
} //end of namespace testinghelpers

View File

@@ -0,0 +1,479 @@
/*
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_gemm.h"
class DGEMMOvrUndr :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // transa
char, // transb
gtint_t, // over_under
gtint_t, // input_range
gtint_t, // m
gtint_t, // n
gtint_t, // k
double, // alpha
double, // beta
gtint_t, // lda_inc
gtint_t, // ldb_inc
gtint_t, // ldc_inc
gtint_t, // ai
gtint_t, // aj
gtint_t, // bi
gtint_t // bj
>> {};
TEST_P(DGEMMOvrUndr, OverflowUnderflow)
{
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 n,t
char transa = std::get<1>(GetParam());
// denotes whether matrix b is n,t
char transb = std::get<2>(GetParam());
// over_under denotes whether overflow or underflow is to be tested
gtint_t over_under = std::get<3>(GetParam());
// input_range denotes the range of values that would be used to populate the matrices
gtint_t input_range = std::get<4>(GetParam());
// matrix size m
gtint_t m = std::get<5>(GetParam());
// matrix size n
gtint_t n = std::get<6>(GetParam());
// matrix size k
gtint_t k = std::get<7>(GetParam());
// specifies alpha value
T alpha = std::get<8>(GetParam());
// specifies beta value
T beta = std::get<9>(GetParam());
// lda, ldb, ldc increments.
// If increments are zero, then the array size matches the matrix size.
// If increments are nonnegative, the array size is bigger than the matrix size.
gtint_t lda_inc = std::get<10>(GetParam());
gtint_t ldb_inc = std::get<11>(GetParam());
gtint_t ldc_inc = std::get<12>(GetParam());
// ai, aj, bi, bj are the indices where overflow/underflow values need to be inserted
gtint_t ai = std::get<13>(GetParam());
gtint_t aj = std::get<14>(GetParam());
gtint_t bi = std::get<15>(GetParam());
gtint_t bj = std::get<16>(GetParam());
// Set the threshold for the errors:
double thresh = 10*m*n*testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_gemm<T>( storage, transa, transb, over_under, input_range, m, n, k, lda_inc, ldb_inc, ldc_inc, ai, aj, bi, bj, alpha, beta, thresh );
}
class DGEMMOUTestPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char, char, char, gtint_t, gtint_t, gtint_t, gtint_t, gtint_t, double, double, gtint_t, gtint_t, gtint_t, gtint_t, gtint_t, gtint_t, gtint_t>> str) const {
char sfm = std::get<0>(str.param);
char tsa = std::get<1>(str.param);
char tsb = std::get<2>(str.param);
gtint_t over_under = std::get<3>(str.param);
gtint_t input_range = std::get<4>(str.param);
gtint_t m = std::get<5>(str.param);
gtint_t n = std::get<6>(str.param);
gtint_t k = std::get<7>(str.param);
double alpha = std::get<8>(str.param);
double beta = std::get<9>(str.param);
gtint_t lda_inc = std::get<10>(str.param);
gtint_t ldb_inc = std::get<11>(str.param);
gtint_t ldc_inc = std::get<12>(str.param);
gtint_t ai = std::get<13>(str.param);
gtint_t aj = std::get<14>(str.param);
gtint_t bi = std::get<15>(str.param);
gtint_t bj = std::get<16>(str.param);
gtint_t lda = testinghelpers::get_leading_dimension( sfm, tsa, m, k, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( sfm, tsb, k, n, ldb_inc );
gtint_t ldc = testinghelpers::get_leading_dimension( sfm, 'n', m, n, ldc_inc );
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name = str_name + "StorageOfCMatrix_" + sfm;
str_name = str_name + "_transa_" + tsa + "_transb_"+ tsb;
std::string over_under_str = ( over_under > 0) ? "underflow": "overflow";
str_name = str_name + "_" + over_under_str;
std::string input_range_str = (input_range < 0) ? "within_limit": (input_range > 0) ? "beyond_limit" : "close_to_limit";
str_name = str_name + "_" + input_range_str;
str_name = str_name + "_m_" + std::to_string(m);
str_name = str_name + "_n_" + std::to_string(n);
str_name = str_name + "_k_" + std::to_string(k);
str_name = str_name + "_A_" + std::to_string(ai) + "_" + std::to_string(aj);
str_name = str_name + "_B_" + std::to_string(bi) + "_" + std::to_string(bj);
std::string alpha_str = ( alpha > 0) ? std::to_string(int(alpha)) : "m" + std::to_string(int(std::abs(alpha)));
str_name = str_name + "_alpha_" + alpha_str;
std::string beta_str = ( beta > 0) ? std::to_string(int(beta)) : "m" + std::to_string(int(std::abs(beta)));
str_name = str_name + "_beta_" + beta_str;
str_name = str_name + "_lda_" + std::to_string(lda);
str_name = str_name + "_ldb_" + std::to_string(ldb);
str_name = str_name + "_ldc_" + std::to_string(ldc);
return str_name;
}
};
/*
Tests for Overflow
An Overflow condition occurs when the result of an operation or computation is larger than the
maximum representable floating point value. For double precision floating points, the largest
representable number is
DBL_MAX = 1.7976931348623158e+308
This test populates matrices with values close to DBL_MAX so that the subsequent operations lead
to values larger than DBL_MAX and hence causes a floating point overflow.
The argument over_under is used to indicate whether the test is an overflow or an underflow test.
over_under = 0 indicates an overflow test
The argument input_range is used to choose the range of values used to populate input matrices
input_range = -1 for values < DBL_MAX
input_range = 0 for values close to DBL_MAX
input_range = 1 for values > DBL_MAX
*/
/* Overflow test for values much less than DBL_MAX */
INSTANTIATE_TEST_SUITE_P(
overflow_within_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(0), // over_under = 0 for overflow
::testing::Values(-1), // input_range = -1 to test values less than DBL_MAX
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values( -1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(3), // increment to the leading dim of a
::testing::Values(3), // increment to the leading dim of b
::testing::Values(3), // increment to the leading dim of c
::testing::Values(100), // ai
::testing::Values(120), // aj
::testing::Values(140), // bi
::testing::Values(110) // bj
),
::DGEMMOUTestPrint()
);
/* Overflow test for values close to DBL_MAX */
INSTANTIATE_TEST_SUITE_P(
overflow_close_to_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(0), // over_under = 0 for overflow
::testing::Values(0), // input_range = 0 to test values close to DBL_MAX
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values( -1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(0), // increment to the leading dim of a
::testing::Values(0), // increment to the leading dim of b
::testing::Values(0), // increment to the leading dim of c
::testing::Values(110), // ai
::testing::Values(130), // aj
::testing::Values(140), // bi
::testing::Values(120) // bj
),
::DGEMMOUTestPrint()
);
/* Overflow test for values close to DBL_MAX and aplha = 0*/
INSTANTIATE_TEST_SUITE_P(
overflow_close_to_limit_alpha0,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(0), // over_under = 0 for overflow
::testing::Values(0), // input_range = 0 to test values close to DBL_MAX
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values(0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(5), // increment to the leading dim of a
::testing::Values(5), // increment to the leading dim of b
::testing::Values(5), // increment to the leading dim of c
::testing::Values(108), // ai
::testing::Values(122), // aj
::testing::Values(145), // bi
::testing::Values(108) // bj
),
::DGEMMOUTestPrint()
);
/* Overflow test for values larger than DBL_MAX */
INSTANTIATE_TEST_SUITE_P(
overflow_beyond_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(0), // over_under = 0 for overflow
::testing::Values(1), // input_range = 1 to test values larger than DBL_MAX
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values( -1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(0), // increment to the leading dim of a
::testing::Values(0), // increment to the leading dim of b
::testing::Values(0), // increment to the leading dim of c
::testing::Values(110), // ai
::testing::Values(140), // aj
::testing::Values(130), // bi
::testing::Values(100) // bj
),
::DGEMMOUTestPrint()
);
/*
Tests for Underflow
An underflow occurs when the result of an operation or a computation is smaller than the
smallest representable floating point number. For double-precision floating points,
the smallest representable number is
DBL_MIN = 2.2250738585072014e-308
This test populates matrices with values close to DBL_MIN so that the subsequent operations
lead to values smaller than DBL_MIN and hence results in a floating point underflow.
The argument over_under is used to indicate whether a test is an overflow or an underflow test.
over_under=1 indicates an underflow test
The argument input_range is used to choose the range of values used to populate input matrices
input_range = -1 for values > DBL_MIN
input_range = 0 for values close to DBL_MIN
input_range = 1 for values < DBL_MIN
*/
/* Underflow test for values larger than DBL_MIN */
INSTANTIATE_TEST_SUITE_P(
underflow_within_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(1), // over_under = 1 for underflow
::testing::Values(-1), // input_range = -1 to test values larger than DBL_MIN
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values( -1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(3), // increment to the leading dim of a
::testing::Values(3), // increment to the leading dim of b
::testing::Values(3), // increment to the leading dim of c
::testing::Values(100), // ai
::testing::Values(120), // aj
::testing::Values(140), // bi
::testing::Values(110) // bj
),
::DGEMMOUTestPrint()
);
/* Underflow test for values close to DBL_MIN */
INSTANTIATE_TEST_SUITE_P(
underflow_close_to_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(1), // over_under = 1 for underflow
::testing::Values(0), // input_range = 0 to test values close to DBL_MIN
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values( -1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(5), // increment to the leading dim of a
::testing::Values(5), // increment to the leading dim of b
::testing::Values(5), // increment to the leading dim of c
::testing::Values(101), // ai
::testing::Values(118), // aj
::testing::Values(132), // bi
::testing::Values(110) // bj
),
::DGEMMOUTestPrint()
);
/* Underflow test for values close to DBL_MIN and alpha = 0 */
INSTANTIATE_TEST_SUITE_P(
underflow_close_to_limit_alpha0,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(1), // over_under = 1 for underflow
::testing::Values(0), // input_range = 0 to test values close to DBL_MIN
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values(0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(0), // increment to the leading dim of a
::testing::Values(0), // increment to the leading dim of b
::testing::Values(0), // increment to the leading dim of c
::testing::Values(117), // ai
::testing::Values(122), // aj
::testing::Values(88), // bi
::testing::Values(42) // bj
),
::DGEMMOUTestPrint()
);
/* Underflow test for values smaller than DBL_MIN */
INSTANTIATE_TEST_SUITE_P(
underflow_beyond_limit,
DGEMMOvrUndr,
::testing::Combine(
// No condition based on storage scheme of matrices
::testing::Values('c'), // storage format
// No conditions based on trans of matrices
::testing::Values('n', 't'), // transa
::testing::Values('n', 't'), // transb
::testing::Values(1), // over_under = 1 for underflow
::testing::Values(1), // input_range = 1 to test values smaller than DBL_MIN
::testing::Values(120, 256, 512), // m
::testing::Values(144, 237, 680), // n
::testing::Values(128, 557, 680), // k
// No condition based on alpha
::testing::Values(-1.0), // alpha
// No condition based on beta
::testing::Values(-1.0), // beta
::testing::Values(3), // increment to the leading dim of a
::testing::Values(3), // increment to the leading dim of b
::testing::Values(3), // increment to the leading dim of c
::testing::Values(44), // ai
::testing::Values(135), // aj
::testing::Values(100), // bi
::testing::Values(105) // bj
),
::DGEMMOUTestPrint()
);

View File

@@ -4,7 +4,7 @@
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
Copyright (C) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -39,6 +39,7 @@
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include <cfloat>
template<typename T>
void test_gemm( char storage, char trnsa, char trnsb, gtint_t m, gtint_t n,
@@ -136,3 +137,110 @@ void test_gemm( char storage, char trnsa, char trnsb, gtint_t m, gtint_t n,
//----------------------------------------------------------
computediff<T>( storage, m, n, c.data(), c_ref.data(), ldc, thresh, true );
}
// Test body used for overflow and underflow checks
template<typename T>
void test_gemm( char storage, char trnsa, char trnsb, gtint_t over_under, gtint_t input_range,
gtint_t m, gtint_t n, gtint_t k, gtint_t lda_inc, gtint_t ldb_inc,
gtint_t ldc_inc, gtint_t ai, gtint_t aj, gtint_t bi, gtint_t bj, T alpha,
T beta, double thresh )
{
// Compute the leading dimensions of a, b, and c.
gtint_t lda = testinghelpers::get_leading_dimension( storage, trnsa, m, k, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( storage, trnsb, k, n, ldb_inc );
gtint_t ldc = testinghelpers::get_leading_dimension( storage, 'n', m, n, ldc_inc );
//----------------------------------------------------------
// Initialize matrices with random numbers
//----------------------------------------------------------
std::vector<T> a,b,c;
/*
Testing for Overflow
======================
For double-precision floating point, the maximum representable number is
DBL_MAX = 1.7976931348623158e+308
Any value higher than DBL_MAX is considered to be an overflow.
over_under=0 indicates Overflow testing
The input matrices are populated with 3 different value ranges based on input_range
|****************************************************************|
| input_range | Expected Input | Expected Output |
|*************|*************************|************************|
| -1 | Values much less than | Exact floating point |
| | DBL_MAX | values |
|*************|*************************|************************|
| 0 | Values close to | Exact floating point |
| | DBL_MAX | values upto DBL_MAX |
| | | |
| | | +/-INF for values |
| | | higher than +/-DBL_MAX |
|*************|*************************|************************|
| 1 | Values much higher than | +/-INF for values |
| | DBL_MAX | higher than +/-DBL_MAX |
| | | |
******************************************************************
Testing for Underflow
========================
For double-precision floating point, the minimum representable number is
DBL_MIN = 2.2250738585072014e-308
Any value lower than DBL_MIN is considered to be an underflow
over_under=1 indicates Underflow testing
The input matrices are populated with 3 different value ranges based on input_range
|******************************************************************|
| input_range | Expected Input | Expected Output |
|*************|**************************|*************************|
| -1 | Values much larger | Exact floating point |
| | than DBL_MIN | values |
|*************|**************************|*************************|
| 0 | Values close to | Exact floating point |
| | DBL_MIN | values upto DBL_MIN |
| | | |
| | | +0 for values |
| | | lower than DBL_MIN |
|*************|**************************|*************************|
| 1 | Values much smaller than | +0 for values |
| | DBL_MIN | smaller than +/-DBL_MIN |
| | | |
********************************************************************
*/
a = testinghelpers::get_random_matrix<T>( 5.5, 10.5, storage, trnsa, m, k, lda,
testinghelpers::datagenerators::ElementType::FP );
b = testinghelpers::get_random_matrix<T>( 3.2, 5.6, storage, trnsb, k, n, ldb,
testinghelpers::datagenerators::ElementType::FP );
c = testinghelpers::get_random_matrix<T>( -5, -2, storage, 'n', m, n, ldc,
testinghelpers::datagenerators::ElementType::FP );
/*
Based on the value of over_under, overflow/underflow values are inserted to the input matrices
at the indices passed as arguments.
*/
testinghelpers::set_overflow_underflow_mat( storage, trnsa, lda, ai, aj, a.data(), over_under, input_range);
testinghelpers::set_overflow_underflow_mat( storage, trnsb, lda, bi, bj, b.data(), over_under, input_range);
std::vector<T> c_ref(c);
// Create a copy of c so that we can check reference results.
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
gemm<T>( storage, trnsa, trnsb, m, n, k, &alpha, a.data(), lda,
b.data(), ldb, &beta, c.data(), ldc );
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_gemm<T>( storage, trnsa, trnsb, m, n, k, alpha,
a.data(), lda, b.data(), ldb, beta, c_ref.data(), ldc );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( storage, m, n, c.data(), c_ref.data(), ldc, thresh, true );
}