From 2c6bf39e4e419049184e99783a0bf1b5d89ac0cd Mon Sep 17 00:00:00 2001 From: aadityansha06 Date: Tue, 14 Jul 2026 08:02:09 +0530 Subject: [PATCH 1/2] 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 --- cblas.h | 10 +- common_interface.h | 8 +- common_level3.h | 8 +- common_param.h | 8 +- interface/geadd.c | 61 +- interface/zgeadd.c | 74 ++- kernel/generic/geadd.c | 89 +-- kernel/generic/zgeadd.c | 101 ++-- utest/test_extensions/test_cgeadd.c | 179 ++++-- utest/test_extensions/test_dgeadd.c | 839 +++++++++++++++------------ utest/test_extensions/test_sgeadd.c | 864 +++++++++++++++------------- utest/test_extensions/test_zgeadd.c | 203 +++++-- 12 files changed, 1474 insertions(+), 970 deletions(-) diff --git a/cblas.h b/cblas.h index f406c20432..9eb70281b9 100644 --- a/cblas.h +++ b/cblas.h @@ -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, diff --git a/common_interface.h b/common_interface.h index 380ce8d081..26107634d1 100644 --- a/common_interface.h +++ b/common_interface.h @@ -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 diff --git a/common_level3.h b/common_level3.h index 64d206a6d1..8399b5b013 100644 --- a/common_level3.h +++ b/common_level3.h @@ -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); diff --git a/common_param.h b/common_param.h index 3245bae6ef..fd20945c4e 100644 --- a/common_param.h +++ b/common_param.h @@ -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; diff --git a/interface/geadd.c b/interface/geadd.c index a2e6d10818..de49d25ba5 100644 --- a/interface/geadd.c +++ b/interface/geadd.c @@ -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; + + + } else{ + + if (lda < MAX(1, m)) info = 5; + } + + if(transc){ + if (ldc < MAX(1, n)) info = 8; - if (lda < MAX(1, m)) info = 5; - if (ldc < MAX(1, m)) 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 (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 = 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); diff --git a/interface/zgeadd.c b/interface/zgeadd.c index de71f27b87..652b9fddc5 100644 --- a/interface/zgeadd.c +++ b/interface/zgeadd.c @@ -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 ( (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 (m < 0) info = 1; } if (order == CblasRowMajor) { @@ -112,13 +140,24 @@ void CNAME(enum CBLAS_ORDER order, t = n; 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; } + + + 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); diff --git a/kernel/generic/geadd.c b/kernel/generic/geadd.c index 062918b8cb..698d3b2fe7 100644 --- a/kernel/generic/geadd.c +++ b/kernel/generic/geadd.c @@ -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 Date: Tue, 14 Jul 2026 08:50:45 +0530 Subject: [PATCH 2/2] Add self to CONTRIBUTORS.md --- CONTRIBUTORS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c6e3a0bd65..39ae88cf7a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -279,3 +279,8 @@ In chronological order: * Nathan Sircombe * [2026-04-16] Add CPU ID for Neoverse V3 hheei + +* Aadityansha Verma + * [2026-07-14] Add independent transpose support for C in GEADD (sgeadd/dgeadd/cgeadd/zgeadd). + +