Add transpose support for C in GEADD (fixes #4646)

Extends GEADD to support independent transposition of both A and C,
matching the behavior of cuBLAS's geam and Apple's Accelerate geadd.
Previously only A could be transposed.

- Add transc parameter across cblas.h, common_interface.h,
  common_level3.h, common_param.h
- Add transc handling to interface/geadd.c and interface/zgeadd.c
- Extend kernel/generic/geadd.c and kernel/generic/zgeadd.c with
  stride logic for transposed C
- Add transpose test coverage (hand-verified 2x2 cases and randomized
  large-matrix tests) for sgeadd, dgeadd, cgeadd, zgeadd
This commit is contained in:
aadityansha06 2026-07-14 08:02:09 +05:30
parent b338322e9a
commit 2c6bf39e4e
12 changed files with 1458 additions and 954 deletions

10
cblas.h
View File

@ -449,13 +449,13 @@ void cblas_cimatcopy(OPENBLAS_CONST enum CBLAS_ORDER CORDER, OPENBLAS_CONST enum
void cblas_zimatcopy(OPENBLAS_CONST enum CBLAS_ORDER CORDER, OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS, OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST double* calpha, double* a,
OPENBLAS_CONST blasint clda, OPENBLAS_CONST blasint cldb);
void cblas_sgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST float calpha, OPENBLAS_CONST float *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST float cbeta,
float *c, OPENBLAS_CONST blasint cldc);
void cblas_dgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST double calpha, OPENBLAS_CONST double *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST double cbeta,
void cblas_sgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_A,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_C,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST float calpha, OPENBLAS_CONST float *a, OPENBLAS_CONST blasint clda,OPENBLAS_CONST float cbeta, float *c,
OPENBLAS_CONST blasint cldc);
void cblas_dgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_A,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_C,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST double calpha, OPENBLAS_CONST double *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST double cbeta,
double *c, OPENBLAS_CONST blasint cldc);
void cblas_cgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST float *calpha, OPENBLAS_CONST float *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST float *cbeta,
void cblas_cgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_A,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_C,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST float *calpha, OPENBLAS_CONST float *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST float *cbeta,
float *c, OPENBLAS_CONST blasint cldc);
void cblas_zgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST double *calpha, OPENBLAS_CONST double *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST double *cbeta,
void cblas_zgeadd(OPENBLAS_CONST enum CBLAS_ORDER CORDER,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_A,OPENBLAS_CONST enum CBLAS_TRANSPOSE CTRANS_C,OPENBLAS_CONST blasint crows, OPENBLAS_CONST blasint ccols, OPENBLAS_CONST double *calpha, OPENBLAS_CONST double *a, OPENBLAS_CONST blasint clda, OPENBLAS_CONST double *cbeta,
double *c, OPENBLAS_CONST blasint cldc);
void cblas_sgemm_batch(OPENBLAS_CONST enum CBLAS_ORDER Order, OPENBLAS_CONST enum CBLAS_TRANSPOSE * TransA_array, OPENBLAS_CONST enum CBLAS_TRANSPOSE * TransB_array, OPENBLAS_CONST blasint * M_array, OPENBLAS_CONST blasint * N_array, OPENBLAS_CONST blasint * K_array,

View File

@ -801,10 +801,10 @@ void BLASFUNC(dimatcopy) (char *, char *, blasint *, blasint *, double *, do
void BLASFUNC(cimatcopy) (char *, char *, blasint *, blasint *, float *, float *, blasint *, blasint *);
void BLASFUNC(zimatcopy) (char *, char *, blasint *, blasint *, double *, double *, blasint *, blasint *);
void BLASFUNC(sgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*);
void BLASFUNC(dgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*);
void BLASFUNC(cgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*);
void BLASFUNC(zgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*);
void BLASFUNC(sgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*,char*, char*);
void BLASFUNC(dgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*,char *, char *);
void BLASFUNC(cgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*,char *, char *);
void BLASFUNC(zgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*,char *, char *);
#ifdef __cplusplus

View File

@ -2050,10 +2050,10 @@ int zimatcopy_k_rnc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
int zimatcopy_k_ctc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
int zimatcopy_k_rtc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
int sgeadd_k(BLASLONG, BLASLONG, float, float*, BLASLONG, float, float *, BLASLONG);
int dgeadd_k(BLASLONG, BLASLONG, double, double*, BLASLONG, double, double *, BLASLONG);
int cgeadd_k(BLASLONG, BLASLONG, float, float, float*, BLASLONG, float, float, float *, BLASLONG);
int zgeadd_k(BLASLONG, BLASLONG, double,double, double*, BLASLONG, double, double, double *, BLASLONG);
int sgeadd_k(BLASLONG, BLASLONG, float, float*, BLASLONG, float, float *, BLASLONG,BLASLONG,BLASLONG);
int dgeadd_k(BLASLONG, BLASLONG, double, double*, BLASLONG, double, double *, BLASLONG,BLASLONG,BLASLONG);
int cgeadd_k(BLASLONG, BLASLONG, float, float, float*, BLASLONG, float, float, float *, BLASLONG,BLASLONG,BLASLONG);
int zgeadd_k(BLASLONG, BLASLONG, double,double, double*, BLASLONG, double, double, double *, BLASLONG,BLASLONG,BLASLONG);
int sgemm_batch_thread(blas_arg_t * queue, BLASLONG nums);
int dgemm_batch_thread(blas_arg_t * queue, BLASLONG nums);

View File

@ -1256,16 +1256,16 @@ int (*shgemv_t) (BLASLONG, BLASLONG, float, hfloat16 *, BLASLONG, hfloat16 *, BL
#endif
#if (BUILD_SINGLE==1)
int (*sgeadd_k) (BLASLONG, BLASLONG, float, float *, BLASLONG, float, float *, BLASLONG);
int (*sgeadd_k) (BLASLONG, BLASLONG, float, float *, BLASLONG, float, float *, BLASLONG, BLASLONG, BLASLONG);
#endif
#if (BUILD_DOUBLE==1)
int (*dgeadd_k) (BLASLONG, BLASLONG, double, double *, BLASLONG, double, double *, BLASLONG);
int (*dgeadd_k) (BLASLONG, BLASLONG, double, double *, BLASLONG, double, double *, BLASLONG, BLASLONG, BLASLONG);
#endif
#if (BUILD_COMPLEX==1)
int (*cgeadd_k) (BLASLONG, BLASLONG, float, float, float *, BLASLONG, float, float, float *, BLASLONG);
int (*cgeadd_k) (BLASLONG, BLASLONG, float, float, float *, BLASLONG, float, float, float *, BLASLONG, BLASLONG, BLASLONG);
#endif
#if (BUILD_COMPLEX16==1)
int (*zgeadd_k) (BLASLONG, BLASLONG, double, double, double *, BLASLONG, double, double, double *, BLASLONG);
int (*zgeadd_k) (BLASLONG, BLASLONG, double, double, double *, BLASLONG, double, double, double *, BLASLONG, BLASLONG, BLASLONG);
#endif
} gotoblas_t;

View File

@ -51,7 +51,7 @@
#ifndef CBLAS
void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
FLOAT *BETA, FLOAT *c, blasint *LDC)
FLOAT *BETA, FLOAT *c, blasint *LDC, char *TRANS_A,char *TRANS_C)
{
blasint m = *M;
@ -62,14 +62,31 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
FLOAT beta = *BETA;
blasint info;
char transa = (*TRANS_A == 'T') || (*TRANS_A == 't') || (*TRANS_A == 'C') || (*TRANS_A == 'c');
char transc = (*TRANS_C == 'T') || (*TRANS_C == 't') || (*TRANS_C == 'C') || (*TRANS_C == 'c');
PRINT_DEBUG_NAME;
info = 0;
if(transa){
if (lda < MAX(1, n))info = 5;
if (lda < MAX(1, m)) info = 5;
if (ldc < MAX(1, m)) info = 8;
} else{
if (lda < MAX(1, m)) info = 5;
}
if(transc){
if (ldc < MAX(1, n)) info = 8;
}else{
if (ldc < MAX(1, m)) info = 8;
}
if (n < 0) info = 2;
if (m < 0) info = 1;
@ -80,7 +97,7 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
}
#else
void CNAME( enum CBLAS_ORDER order, blasint m, blasint n, FLOAT alpha, FLOAT *a, blasint lda, FLOAT beta,
void CNAME( enum CBLAS_ORDER order,enum CBLAS_TRANSPOSE transa, enum CBLAS_TRANSPOSE transc,blasint m, blasint n, FLOAT alpha, FLOAT *a, blasint lda, FLOAT beta,
FLOAT *c, blasint ldc)
{
/*
@ -100,9 +117,17 @@ void CNAME(enum CBLAS_ORDER order,
if (order == CblasColMajor) {
info = -1;
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
if (ldc < MAX(1, m)) info = 8;
} else {
if (ldc < MAX(1, n)) info = 8;
}
if (ldc < MAX(1, m)) info = 8;
if (lda < MAX(1, m)) info = 5;
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
if (lda < MAX(1, m)) info = 5;
} else {
if (lda < MAX(1, n)) info = 5;
}
if (n < 0) info = 2;
if (m < 0) info = 1;
@ -115,8 +140,17 @@ void CNAME(enum CBLAS_ORDER order,
n = m;
m = t;
if (ldc < MAX(1, m)) info = 8;
if (lda < MAX(1, m)) info = 5;
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
if (ldc < MAX(1, m)) info = 8;
} else {
if (ldc < MAX(1, n)) info = 8;
}
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
if (lda < MAX(1, m)) info = 5;
} else {
if (lda < MAX(1, n)) info = 5;
}
if (n < 0) info = 1;
if (m < 0) info = 2;
}
@ -136,7 +170,14 @@ void CNAME(enum CBLAS_ORDER order,
FUNCTION_PROFILE_START();
GEADD_K(m,n,alpha, a, lda, beta, c, ldc);
GEADD_K(m,n,alpha, a, lda, beta, c, ldc,
#ifdef CBLAS
(transa == CblasTrans) || (transa == CblasConjTrans),
(transc == CblasTrans) || (transc == CblasConjTrans)
#else
transa, transc
#endif
);
FUNCTION_PROFILE_END(1, 2* m * n , 2 * m * n);

View File

@ -51,7 +51,7 @@
#ifndef CBLAS
void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
FLOAT *BETA, FLOAT *c, blasint *LDC)
FLOAT *BETA, FLOAT *c, blasint *LDC,char *TRANS_A,char *TRANS_C)
{
blasint m = *M;
@ -60,14 +60,34 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
blasint ldc = *LDC;
blasint info;
char transa = (*TRANS_A == 'T') || (*TRANS_A == 't') || (*TRANS_A == 'C') || (*TRANS_A == 'c');
char transc = (*TRANS_C == 'T') || (*TRANS_C == 't') || (*TRANS_C == 'C') || (*TRANS_C == 'c');
PRINT_DEBUG_NAME;
info = 0;
if (lda < MAX(1, m)) info = 5;
if (ldc < MAX(1, m)) info = 8;
if(transa){
if (lda < MAX(1, n))info = 5;
} else{
if (lda < MAX(1, m)) info = 5;
}
if(transc){
if (ldc < MAX(1, n)) info = 8;
}else{
if (ldc < MAX(1, m)) info = 8;
}
if (n < 0) info = 2;
if (m < 0) info = 1;
@ -78,7 +98,7 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
}
#else
void CNAME( enum CBLAS_ORDER order, blasint m, blasint n, FLOAT *ALPHA, FLOAT *a, blasint lda, FLOAT *BETA,
void CNAME( enum CBLAS_ORDER order,enum CBLAS_TRANSPOSE transa, enum CBLAS_TRANSPOSE transc, blasint m, blasint n, FLOAT *ALPHA, FLOAT *a, blasint lda, FLOAT *BETA,
FLOAT *c, blasint ldc)
{
/*
@ -99,11 +119,19 @@ void CNAME(enum CBLAS_ORDER order,
info = -1;
if (ldc < MAX(1, m)) info = 8;
if (lda < MAX(1, m)) info = 5;
if (n < 0) info = 2;
if (m < 0) info = 1;
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
if (ldc < MAX(1, m)) info = 8;
} else {
if (ldc < MAX(1, n)) info = 8;
}
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
if (lda < MAX(1, m)) info = 5;
} else {
if (lda < MAX(1, n)) info = 5;
}
if (n < 0) info = 2;
if (m < 0) info = 1;
}
if (order == CblasRowMajor) {
@ -112,13 +140,24 @@ void CNAME(enum CBLAS_ORDER order,
t = n;
n = m;
m = t;
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
if (ldc < MAX(1, m)) info = 8;
} else {
if (ldc < MAX(1, n)) info = 8;
}
if (ldc < MAX(1, m)) info = 8;
if (lda < MAX(1, m)) info = 5;
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
if (lda < MAX(1, m)) info = 5;
} else {
if (lda < MAX(1, n)) info = 5;
}
if (n < 0) info = 1;
if (m < 0) info = 2;
}
if (info >= 0) {
BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
return;
@ -134,7 +173,18 @@ void CNAME(enum CBLAS_ORDER order,
FUNCTION_PROFILE_START();
GEADD_K(m,n,ALPHA[0],ALPHA[1], a, lda, BETA[0], BETA[1], c, ldc);
GEADD_K(m,n,ALPHA[0],ALPHA[1], a, lda, BETA[0], BETA[1], c, ldc,
#ifdef CBLAS
(transa == CblasTrans) || (transa == CblasConjTrans),
(transc == CblasTrans) || (transc == CblasConjTrans)
#else
transa, transc
#endif
);
FUNCTION_PROFILE_END(1, 2* m * n , 2 * m * n);

View File

@ -17,48 +17,73 @@ 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 OPENBLAS PROJECT 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.
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 "common.h"
int CNAME(BLASLONG rows, BLASLONG cols, FLOAT alpha, FLOAT *a, BLASLONG lda,
FLOAT beta, FLOAT *b, BLASLONG ldb, BLASLONG transa,
BLASLONG transb) {
BLASLONG i;
FLOAT *aptr, *bptr;
int CNAME(BLASLONG rows, BLASLONG cols, FLOAT alpha, FLOAT *a, BLASLONG lda, FLOAT beta, FLOAT *b, BLASLONG ldb)
{
BLASLONG i;
FLOAT *aptr,*bptr;
if (rows <= 0)
return (0);
if (cols <= 0)
return (0);
if ( rows <= 0 ) return(0);
if ( cols <= 0 ) return(0);
aptr = a;
bptr = b;
aptr = a;
bptr = b;
if (alpha == 0.0) {
if (!transb) {
for (i = 0; i < cols; i++) {
if ( alpha == 0.0 )
{
for ( i=0; i<cols ; i++ )
{
SCAL_K(rows, 0,0, beta, bptr, 1, NULL, 0,NULL,0);
bptr+=ldb;
}
SCAL_K(rows, 0, 0, beta, bptr, 1, NULL, 0, NULL, 0);
bptr += ldb;
}
} else {
for (i = 0; i < cols; i++) {
return(0);
}
SCAL_K(rows, 0, 0, beta, bptr, ldb, NULL, 0, NULL, 0);
bptr += 1;
}
}
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alpha, aptr, 1, beta, bptr, 1);
aptr += lda;
bptr += ldb;
}
return (0);
}
if (!transa && !transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alpha, aptr, 1, beta, bptr, 1);
aptr += lda;
bptr += ldb;
}
} else if (transa && !transb) {
for (i = 0; i < cols; i++) {
return(0);
AXPBY_K(rows, alpha, aptr, lda, beta, bptr, 1);
aptr += 1;
bptr += ldb;
}
} else if (!transa && transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alpha, aptr, 1, beta, bptr, ldb);
aptr += lda;
bptr += 1;
}
} else if (transa && transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alpha, aptr, lda, beta, bptr, ldb);
aptr += 1;
bptr += 1;
}
}
return (0);
}

View File

@ -17,49 +17,72 @@ 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 OPENBLAS PROJECT 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.
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 "common.h"
int CNAME(BLASLONG rows, BLASLONG cols, FLOAT alphar, FLOAT alphai, FLOAT *a,
BLASLONG lda, FLOAT betar, FLOAT betai, FLOAT *b, BLASLONG ldb,
BLASLONG transa, BLASLONG transb) {
BLASLONG i;
FLOAT *aptr, *bptr;
BLASLONG lda_elem = lda;
BLASLONG ldb_elem = ldb;
if (rows <= 0)
return (0);
if (cols <= 0)
return (0);
int CNAME(BLASLONG rows, BLASLONG cols, FLOAT alphar, FLOAT alphai, FLOAT *a, BLASLONG lda, FLOAT betar, FLOAT betai , FLOAT *b, BLASLONG ldb)
{
BLASLONG i;
FLOAT *aptr,*bptr;
if ( rows <= 0 ) return(0);
if ( cols <= 0 ) return(0);
aptr = a;
bptr = b;
lda *= 2;
ldb *= 2;
if ( alphar == 0.0 && alphai == 0.0 )
{
for ( i=0; i<cols ; i++ )
{
SCAL_K(rows, 0,0, betar, betai, bptr, 1, NULL, 0,NULL,0);
bptr+=ldb;
}
return(0);
}
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alphar, alphai, aptr, 1, betar, betai, bptr, 1);
aptr += lda;
bptr += ldb;
}
return(0);
aptr = a;
bptr = b;
lda *= 2;
ldb *= 2;
if (alphar == 0.0 && alphai == 0.0) {
if (!transb) {
for (i = 0; i < cols; i++) {
SCAL_K(rows, 0, 0, betar, betai, bptr, 1, NULL, 0, NULL, 0);
bptr += ldb;
}
} else {
for (i = 0; i < cols; i++) {
SCAL_K(rows, 0, 0, betar, betai, bptr, ldb_elem, NULL, 0, NULL, 0);
bptr += 2;
}
}
return (0);
}
if (!transa && !transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alphar, alphai, aptr, 1, betar, betai, bptr, 1);
aptr += lda;
bptr += ldb;
}
} else if (transa && !transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alphar, alphai, aptr, lda_elem, betar, betai, bptr, 1);
aptr += 2;
bptr += ldb;
}
} else if (!transa && transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alphar, alphai, aptr, 1, betar, betai, bptr, ldb_elem);
aptr += lda;
bptr += 2;
}
} else if (transa && transb) {
for (i = 0; i < cols; i++) {
AXPBY_K(rows, alphar, alphai, aptr, lda_elem, betar, betai, bptr,
ldb_elem);
aptr += 2;
bptr += 2;
}
}
return (0);
}

View File

@ -57,21 +57,27 @@ static struct DATA_CGEADD data_cgeadd;
* param beta - scaling factor for matrix C
* param cptr - refer to matrix C
* param ldc - leading dimension of C
* param transa - Traspose of A
* param transc - Transpose of C
*/
static void cgeadd_trusted(blasint m, blasint n, float *alpha, float *aptr,
blasint lda, float *beta, float *cptr, blasint ldc)
blasint lda, float *beta, float *cptr, blasint ldc,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc)
{
blasint i;
blasint one=1;
blasint inc_a = (transa == CblasTrans) ? lda : 1;
blasint inc_c = (transc == CblasTrans) ? ldc : 1;
lda *= 2;
ldc *= 2;
blasint step_a = (transa == CblasTrans) ? 1 : lda;
blasint step_c = (transc == CblasTrans) ? 1 : ldc;
for (i = 0; i < n; i++)
{
BLASFUNC(caxpby)(&m, alpha, aptr, &one, beta, cptr, &one);
aptr += lda;
cptr += ldc;
BLASFUNC(caxpby)(&m, alpha, aptr, &inc_a, beta, cptr, &inc_c);
aptr += step_a*2;
cptr += step_c*2;
}
}
@ -91,6 +97,8 @@ static void cgeadd_trusted(blasint m, blasint n, float *alpha, float *aptr,
* return norm of differences
*/
static float check_cgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc,
blasint m, blasint n, float *alpha, blasint lda,
float *beta, blasint ldc)
{
@ -112,14 +120,19 @@ static float check_cgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
data_cgeadd.c_verify[i] = data_cgeadd.c_test[i];
cgeadd_trusted(cols, rows, alpha, data_cgeadd.a_test, lda,
beta, data_cgeadd.c_verify, ldc);
beta, data_cgeadd.c_verify, ldc,transa, transc);
if (api == 'F')
if (api == 'F'){
char transa_f = (transa == CblasTrans) ? 'T' : 'N';
char transc_f = (transc == CblasTrans) ? 'T' : 'N';
BLASFUNC(cgeadd)(&m, &n, alpha, data_cgeadd.a_test, &lda,
beta, data_cgeadd.c_test, &ldc);
beta, data_cgeadd.c_test, &ldc,&transa_f, &transc_f);
}
#ifndef NO_CBLAS
else
cblas_cgeadd(order, m, n, alpha, data_cgeadd.a_test, lda,
cblas_cgeadd(order,transa,transc, m, n, alpha, data_cgeadd.a_test, lda,
beta, data_cgeadd.c_test, ldc);
#endif
@ -142,6 +155,8 @@ static float check_cgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
* return TRUE if everything is ok, otherwise FALSE
*/
static int check_badargs(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc,
blasint m, blasint n, blasint lda,
blasint ldc, int expected_info)
{
@ -150,12 +165,17 @@ static int check_badargs(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
set_xerbla("CGEADD ", expected_info);
if (api == 'F')
if (api == 'F'){
char transa_f = (transa == CblasTrans) ? 'T' : 'N';
char transc_f = (transc == CblasTrans) ? 'T' : 'N';
BLASFUNC(cgeadd)(&m, &n, alpha, data_cgeadd.a_test, &lda,
beta, data_cgeadd.c_test, &ldc);
beta, data_cgeadd.c_test, &ldc,&transa_f, &transc_f);
}
#ifndef NO_CBLAS
else
cblas_cgeadd(order, m, n, alpha, data_cgeadd.a_test, lda,
cblas_cgeadd(order,transa, transc, m, n, alpha, data_cgeadd.a_test, lda,
beta, data_cgeadd.c_test, ldc);
#endif
@ -183,7 +203,7 @@ CTEST(cgeadd, matrix_n_100_m_100)
float alpha[] = {3.0f, 2.0f};
float beta[] = {1.0f, 3.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans,m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -210,7 +230,7 @@ CTEST(cgeadd, matrix_n_100_m_100_alpha_zero)
float alpha[] = {0.0f, 0.0f};
float beta[] = {2.5f, 1.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -237,7 +257,7 @@ CTEST(cgeadd, matrix_n_100_m_100_beta_zero)
float alpha[] = {3.0f, 1.5f};
float beta[] = {0.0f, 0.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -264,7 +284,7 @@ CTEST(cgeadd, matrix_n_100_m_100_alpha_beta_zero)
float alpha[] = {0.0f, 0.0f};
float beta[] = {0.0f, 0.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -290,7 +310,7 @@ CTEST(cgeadd, matrix_n_100_m_50)
float alpha[] = {1.0f, 1.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -313,7 +333,7 @@ CTEST(cgeadd, xerbla_n_invalid)
int expected_info = 2;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -335,7 +355,7 @@ CTEST(cgeadd, xerbla_m_invalid)
int expected_info = 1;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -356,7 +376,7 @@ CTEST(cgeadd, xerbla_lda_invalid)
int expected_info = 5;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -377,7 +397,7 @@ CTEST(cgeadd, xerbla_ldc_invalid)
int expected_info = 8;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -398,7 +418,7 @@ CTEST(cgeadd, n_zero)
float alpha[] = {1.0f, 1.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -420,7 +440,7 @@ CTEST(cgeadd, m_zero)
float alpha[] = {1.0f, 1.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('F', order, m, n, alpha, lda, beta, ldc);
float norm = check_cgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
@ -447,7 +467,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_100)
float alpha[] = {2.0f, 1.0f};
float beta[] = {1.0f, 3.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -475,7 +495,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_100_row_major)
float alpha[] = {4.0f, 1.5f};
float beta[] = {2.0f, 1.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -503,7 +523,7 @@ CTEST(cgeadd, c_api_matrix_n_50_m_100_row_major)
float alpha[] = {3.0f, 2.5f};
float beta[] = {1.0f, 2.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -532,7 +552,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_100_alpha_zero)
float alpha[] = {0.0f, 0.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -561,7 +581,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_100_beta_zero)
float alpha[] = {3.0f, 1.5f};
float beta[] = {0.0f, 0.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -590,7 +610,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_100_alpha_beta_zero)
float alpha[] = {0.0f, 0.0f};
float beta[] = {0.0f, 0.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -617,7 +637,7 @@ CTEST(cgeadd, c_api_matrix_n_100_m_50)
float alpha[] = {2.0f, 3.0f};
float beta[] = {2.0f, 4.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -641,7 +661,7 @@ CTEST(cgeadd, c_api_xerbla_invalid_order)
int expected_info = 0;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -665,7 +685,7 @@ CTEST(cgeadd, c_api_xerbla_n_invalid)
int expected_info = 2;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -689,7 +709,7 @@ CTEST(cgeadd, c_api_xerbla_n_invalid_row_major)
int expected_info = 2;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -713,7 +733,7 @@ CTEST(cgeadd, c_api_xerbla_m_invalid)
int expected_info = 1;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -737,7 +757,7 @@ CTEST(cgeadd, c_api_xerbla_m_invalid_row_major)
int expected_info = 1;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -760,7 +780,7 @@ CTEST(cgeadd, c_api_xerbla_lda_invalid)
int expected_info = 5;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -783,7 +803,7 @@ CTEST(cgeadd, c_api_xerbla_lda_invalid_row_major)
int expected_info = 5;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -806,7 +826,7 @@ CTEST(cgeadd, c_api_xerbla_ldc_invalid)
int expected_info = 8;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -829,7 +849,7 @@ CTEST(cgeadd, c_api_xerbla_ldc_invalid_row_major)
int expected_info = 8;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -852,7 +872,7 @@ CTEST(cgeadd, c_api_n_zero)
float alpha[] = {1.0f, 1.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
@ -877,10 +897,83 @@ CTEST(cgeadd, c_api_m_zero)
float alpha[] = {1.0f, 1.0f};
float beta[] = {1.0f, 1.0f};
float norm = check_cgeadd('C', order, m, n, alpha,
float norm = check_cgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
CTEST(cgeadd, c_api_matrix_2x2_transA) {
blasint m = 2;
blasint n = 2;
blasint lda = 2;
blasint ldc = 2;
float alpha[] = {1.0f, 0.0f};
float beta[] = {0.0f, 0.0f};
float a_test[8] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
float c_test[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
float c_verify[8] = {1.0f, 2.0f, 5.0f, 6.0f, 3.0f, 4.0f, 7.0f, 8.0f};
cblas_cgeadd(CblasColMajor, CblasTrans, CblasNoTrans, m, n, alpha, a_test,
lda, beta, c_test, ldc);
blasint i;
for (i = 0; i < 8; i++) {
ASSERT_DBL_NEAR_TOL(c_verify[i], c_test[i], SINGLE_EPS);
}
}
/**
* Custom C API specific test
* Test BOTH transposed (C^T = A^T) with a simple 2x2 complex float matrix
*/
CTEST(cgeadd, c_api_matrix_2x2_transA_transC) {
blasint m = 2;
blasint n = 2;
blasint lda = 2;
blasint ldc = 2;
float alpha[] = {1.0f, 0.0f};
float beta[] = {0.0f, 0.0f};
float a_test[8] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
float c_test[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
float c_verify[8] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
cblas_cgeadd(CblasColMajor, CblasTrans, CblasTrans, m, n, alpha, a_test, lda,
beta, c_test, ldc);
blasint i;
for (i = 0; i < 8; i++) {
ASSERT_DBL_NEAR_TOL(c_verify[i], c_test[i], SINGLE_EPS);
}
}
/**
* C API specific test - Transposed A (Complex Single Precision)
* Fuzzes your core complex float pointer math against a large 100x100 random matrix.
*/
CTEST(cgeadd, c_api_matrix_n_100_m_100_transA) {
CBLAS_ORDER order = CblasColMajor;
blasint n = N;
blasint m = M;
blasint lda = n;
blasint ldc = m;
float alpha[] = {2.0f, -1.0f};
float beta[] = {1.5f, 3.0f};
float norm = check_cgeadd('C', order, CblasTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0f, norm, SINGLE_EPS);
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -57,22 +57,28 @@ static struct DATA_ZGEADD data_zgeadd;
* param beta - scaling factor for matrix C
* param cptr - refer to matrix C
* param ldc - leading dimension of C
* param transa - Traspose of A
* param transc - Transpose of C
*/
static void zgeadd_trusted(blasint m, blasint n, double *alpha, double *aptr,
blasint lda, double *beta, double *cptr, blasint ldc)
blasint lda, double *beta, double *cptr, blasint ldc,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc)
{
blasint i;
blasint one=1;
blasint inc_a = (transa == CblasTrans) ? lda : 1;
blasint inc_c = (transc == CblasTrans) ? ldc : 1;
lda *= 2;
ldc *= 2;
blasint step_a = (transa == CblasTrans) ? 1 : lda;
blasint step_c = (transc == CblasTrans) ? 1 : ldc;
for (i = 0; i < n; i++) {
BLASFUNC(zaxpby)(&m, alpha, aptr, &inc_a, beta, cptr, &inc_c);
aptr += step_a*2;
cptr += step_c*2;
}
for (i = 0; i < n; i++)
{
BLASFUNC(zaxpby)(&m, alpha, aptr, &one, beta, cptr, &one);
aptr += lda;
cptr += ldc;
}
}
/**
@ -91,6 +97,8 @@ static void zgeadd_trusted(blasint m, blasint n, double *alpha, double *aptr,
* return norm of differences
*/
static double check_zgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc,
blasint m, blasint n, double *alpha, blasint lda,
double *beta, blasint ldc)
{
@ -103,23 +111,27 @@ static double check_zgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
cols = n;
}
// Fill matrix A, C
drand_generate(data_zgeadd.a_test, lda * rows * 2);
drand_generate(data_zgeadd.c_test, ldc * rows * 2);
// Copy matrix C for zgeadd
for (i = 0; i < ldc * rows * 2; i++)
data_zgeadd.c_verify[i] = data_zgeadd.c_test[i];
zgeadd_trusted(cols, rows, alpha, data_zgeadd.a_test, lda,
beta, data_zgeadd.c_verify, ldc);
beta, data_zgeadd.c_verify, ldc,transa, transc);
if (api == 'F')
BLASFUNC(zgeadd)(&m, &n, alpha, data_zgeadd.a_test, &lda,
beta, data_zgeadd.c_test, &ldc);
if (api == 'F'){
char transa_f = (transa == CblasTrans) ? 'T' : 'N';
char transc_f = (transc == CblasTrans) ? 'T' : 'N';
BLASFUNC(zgeadd)(&m, &n, alpha, data_zgeadd.a_test, &lda,
beta, data_zgeadd.c_test, &ldc, &transa_f, &transc_f);
}
#ifndef NO_CBLAS
else
cblas_zgeadd(order, m, n, alpha, data_zgeadd.a_test, lda,
cblas_zgeadd(order,transa,transc, m, n, alpha, data_zgeadd.a_test, lda,
beta, data_zgeadd.c_test, ldc);
#endif
@ -133,6 +145,8 @@ static double check_zgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
*
* param api - specifies Fortran or C API
* param order - specifies whether A and C stored in
* param transa - Traspose of A
* param transc - Transpose of C
* row-major order or column-major order
* param m - number of rows of A and C
* param n - number of columns of A and C
@ -142,6 +156,8 @@ static double check_zgeadd(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
* return TRUE if everything is ok, otherwise FALSE
*/
static int check_badargs(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transa,
OPENBLAS_CONST enum CBLAS_TRANSPOSE transc,
blasint m, blasint n, blasint lda,
blasint ldc, int expected_info)
{
@ -150,12 +166,16 @@ static int check_badargs(char api, OPENBLAS_CONST enum CBLAS_ORDER order,
set_xerbla("ZGEADD ", expected_info);
if (api == 'F')
if (api == 'F'){
char transa_f = (transa == CblasTrans) ? 'T' : 'N';
char transc_f = (transc == CblasTrans) ? 'T' : 'N';
BLASFUNC(zgeadd)(&m, &n, alpha, data_zgeadd.a_test, &lda,
beta, data_zgeadd.c_test, &ldc);
beta, data_zgeadd.c_test, &ldc,&transa_f, &transc_f);
}
#ifndef NO_CBLAS
else
cblas_zgeadd(order, m, n, alpha, data_zgeadd.a_test, lda,
cblas_zgeadd(order,transa, transc, m, n, alpha, data_zgeadd.a_test, lda,
beta, data_zgeadd.c_test, ldc);
#endif
@ -183,7 +203,7 @@ CTEST(zgeadd, matrix_n_100_m_100)
double alpha[] = {3.0, 2.0};
double beta[] = {1.0, 3.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -210,7 +230,7 @@ CTEST(zgeadd, matrix_n_100_m_100_alpha_zero)
double alpha[] = {0.0, 0.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -237,7 +257,7 @@ CTEST(zgeadd, matrix_n_100_m_100_beta_zero)
double alpha[] = {3.0, 1.5};
double beta[] = {0.0, 0.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -264,7 +284,7 @@ CTEST(zgeadd, matrix_n_100_m_100_alpha_beta_zero)
double alpha[] = {0.0, 0.0};
double beta[] = {0.0, 0.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -290,7 +310,7 @@ CTEST(zgeadd, matrix_n_100_m_50)
double alpha[] = {1.0, 1.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -313,7 +333,7 @@ CTEST(zgeadd, xerbla_n_invalid)
int expected_info = 2;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -335,7 +355,7 @@ CTEST(zgeadd, xerbla_m_invalid)
int expected_info = 1;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -356,7 +376,7 @@ CTEST(zgeadd, xerbla_lda_invalid)
int expected_info = 5;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -377,7 +397,7 @@ CTEST(zgeadd, xerbla_ldc_invalid)
int expected_info = 8;
int passed = check_badargs('F', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('F', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -398,7 +418,7 @@ CTEST(zgeadd, n_zero)
double alpha[] = {1.0, 1.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -420,7 +440,7 @@ CTEST(zgeadd, m_zero)
double alpha[] = {1.0, 1.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('F', order, m, n, alpha, lda, beta, ldc);
double norm = check_zgeadd('F', order,CblasNoTrans, CblasNoTrans, m, n, alpha, lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
@ -448,7 +468,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_100)
double alpha[] = {2.0, 1.0};
double beta[] = {1.0, 3.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -476,7 +496,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_100_row_major)
double alpha[] = {4.0, 1.5};
double beta[] = {2.0, 1.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -504,7 +524,7 @@ CTEST(zgeadd, c_api_matrix_n_50_m_100_row_major)
double alpha[] = {3.0, 2.5};
double beta[] = {1.0, 2.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -533,7 +553,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_100_alpha_zero)
double alpha[] = {0.0, 0.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -562,7 +582,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_100_beta_zero)
double alpha[] = {3.0, 1.5};
double beta[] = {0.0, 0.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -591,7 +611,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_100_alpha_beta_zero)
double alpha[] = {0.0, 0.0};
double beta[] = {0.0, 0.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -618,7 +638,7 @@ CTEST(zgeadd, c_api_matrix_n_100_m_50)
double alpha[] = {2.0, 3.0};
double beta[] = {2.0, 4.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -642,7 +662,7 @@ CTEST(zgeadd, c_api_xerbla_invalid_order)
int expected_info = 0;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -666,7 +686,7 @@ CTEST(zgeadd, c_api_xerbla_n_invalid)
int expected_info = 2;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -690,7 +710,7 @@ CTEST(zgeadd, c_api_xerbla_n_invalid_row_major)
int expected_info = 2;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -714,7 +734,7 @@ CTEST(zgeadd, c_api_xerbla_m_invalid)
int expected_info = 1;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -738,7 +758,7 @@ CTEST(zgeadd, c_api_xerbla_m_invalid_row_major)
int expected_info = 1;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -761,7 +781,7 @@ CTEST(zgeadd, c_api_xerbla_lda_invalid)
int expected_info = 5;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -784,7 +804,7 @@ CTEST(zgeadd, c_api_xerbla_lda_invalid_row_major)
int expected_info = 5;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -807,7 +827,7 @@ CTEST(zgeadd, c_api_xerbla_ldc_invalid)
int expected_info = 8;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -830,7 +850,7 @@ CTEST(zgeadd, c_api_xerbla_ldc_invalid_row_major)
int expected_info = 8;
int passed = check_badargs('C', order, m, n, lda, ldc, expected_info);
int passed = check_badargs('C', order,CblasNoTrans, CblasNoTrans, m, n, lda, ldc, expected_info);
ASSERT_EQUAL(TRUE, passed);
}
@ -853,7 +873,7 @@ CTEST(zgeadd, c_api_n_zero)
double alpha[] = {1.0, 1.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
@ -878,10 +898,95 @@ CTEST(zgeadd, c_api_m_zero)
double alpha[] = {1.0, 1.0};
double beta[] = {1.0, 1.0};
double norm = check_zgeadd('C', order, m, n, alpha,
double norm = check_zgeadd('C', order,CblasNoTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
/**
* Custom C API specific test
* Test A transposed (C = A^T) with a simple 2x2 complex matrix
* This verifies the manual +2 pointer increments and complex array mapping.
*/
CTEST(zgeadd, c_api_matrix_2x2_transA) {
blasint m = 2;
blasint n = 2;
blasint lda = 2;
blasint ldc = 2;
double alpha[] = {1.0, 0.0};
double beta[] = {0.0, 0.0};
double a_test[8] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
double c_test[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
double c_verify[8] = {1.0, 2.0, 5.0, 6.0, 3.0, 4.0, 7.0, 8.0};
cblas_zgeadd(CblasColMajor, CblasTrans, CblasNoTrans, m, n, alpha, a_test,
lda, beta, c_test, ldc);
blasint i;
for (i = 0; i < 8; i++) {
ASSERT_DBL_NEAR_TOL(c_verify[i], c_test[i], DOUBLE_EPS);
}
}
/**
* Custom C API specific test
* Test BOTH transposed (C^T = A^T) with a simple 2x2 complex matrix
*/
CTEST(zgeadd, c_api_matrix_2x2_transA_transC) {
blasint m = 2;
blasint n = 2;
blasint lda = 2;
blasint ldc = 2;
double alpha[] = {1.0, 0.0};
double beta[] = {0.0, 0.0};
double a_test[8] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
double c_test[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
double c_verify[8] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
cblas_zgeadd(CblasColMajor, CblasTrans, CblasTrans, m, n, alpha, a_test, lda,
beta, c_test, ldc);
blasint i;
for (i = 0; i < 8; i++) {
ASSERT_DBL_NEAR_TOL(c_verify[i], c_test[i], DOUBLE_EPS);
}
}
/**
* C API specific test - Transposed A (Complex Double Precision)
* Fuzzes your core complex pointer math against a large 100x100 random matrix.
*/
CTEST(zgeadd, c_api_matrix_n_100_m_100_transA) {
CBLAS_ORDER order = CblasColMajor;
blasint n = N;
blasint m = M;
blasint lda = n;
blasint ldc = m;
double alpha[] = {2.0, -1.0};
double beta[] = {1.5, 3.0};
double norm = check_zgeadd('C', order, CblasTrans, CblasNoTrans, m, n, alpha,
lda, beta, ldc);
ASSERT_DBL_NEAR_TOL(0.0, norm, DOUBLE_EPS);
}
#endif
#endif