Skip to content

Commit 3e48730

Browse files
authored
Add transpose support for C in GEADD (fixes #4646) (#5913)
* 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 * Add self to CONTRIBUTORS.md
2 parents dc3aa2c + aade7ec commit 3e48730

13 files changed

Lines changed: 1479 additions & 970 deletions

File tree

CONTRIBUTORS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,8 @@ In chronological order:
279279
* Nathan Sircombe <nathan.sircombe@arm.com>
280280
* [2026-04-16] Add CPU ID for Neoverse V3
281281
hheei <hheei@users.noreply.github.com>
282+
283+
* Aadityansha Verma <https://github.com/aadityansha06>
284+
* [2026-07-14] Add independent transpose support for C in GEADD (sgeadd/dgeadd/cgeadd/zgeadd).
285+
286+

cblas.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -449,13 +449,13 @@ void cblas_cimatcopy(OPENBLAS_CONST enum CBLAS_ORDER CORDER, OPENBLAS_CONST enum
449449
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,
450450
OPENBLAS_CONST blasint clda, OPENBLAS_CONST blasint cldb);
451451

452-
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,
453-
float *c, OPENBLAS_CONST blasint cldc);
454-
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,
452+
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,
453+
OPENBLAS_CONST blasint cldc);
454+
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,
455455
double *c, OPENBLAS_CONST blasint cldc);
456-
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,
456+
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,
457457
float *c, OPENBLAS_CONST blasint cldc);
458-
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,
458+
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,
459459
double *c, OPENBLAS_CONST blasint cldc);
460460

461461
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,

common_interface.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,10 +801,10 @@ void BLASFUNC(dimatcopy) (char *, char *, blasint *, blasint *, double *, do
801801
void BLASFUNC(cimatcopy) (char *, char *, blasint *, blasint *, float *, float *, blasint *, blasint *);
802802
void BLASFUNC(zimatcopy) (char *, char *, blasint *, blasint *, double *, double *, blasint *, blasint *);
803803

804-
void BLASFUNC(sgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*);
805-
void BLASFUNC(dgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*);
806-
void BLASFUNC(cgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*);
807-
void BLASFUNC(zgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*);
804+
void BLASFUNC(sgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*,char*, char*);
805+
void BLASFUNC(dgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*,char *, char *);
806+
void BLASFUNC(cgeadd) (blasint *, blasint *, float *, float *, blasint *, float *, float *, blasint*,char *, char *);
807+
void BLASFUNC(zgeadd) (blasint *, blasint *, double *, double *, blasint *, double *, double *, blasint*,char *, char *);
808808

809809

810810
#ifdef __cplusplus

common_level3.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,10 +2050,10 @@ int zimatcopy_k_rnc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
20502050
int zimatcopy_k_ctc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
20512051
int zimatcopy_k_rtc(BLASLONG, BLASLONG, double, double, double *, BLASLONG);
20522052

2053-
int sgeadd_k(BLASLONG, BLASLONG, float, float*, BLASLONG, float, float *, BLASLONG);
2054-
int dgeadd_k(BLASLONG, BLASLONG, double, double*, BLASLONG, double, double *, BLASLONG);
2055-
int cgeadd_k(BLASLONG, BLASLONG, float, float, float*, BLASLONG, float, float, float *, BLASLONG);
2056-
int zgeadd_k(BLASLONG, BLASLONG, double,double, double*, BLASLONG, double, double, double *, BLASLONG);
2053+
int sgeadd_k(BLASLONG, BLASLONG, float, float*, BLASLONG, float, float *, BLASLONG,BLASLONG,BLASLONG);
2054+
int dgeadd_k(BLASLONG, BLASLONG, double, double*, BLASLONG, double, double *, BLASLONG,BLASLONG,BLASLONG);
2055+
int cgeadd_k(BLASLONG, BLASLONG, float, float, float*, BLASLONG, float, float, float *, BLASLONG,BLASLONG,BLASLONG);
2056+
int zgeadd_k(BLASLONG, BLASLONG, double,double, double*, BLASLONG, double, double, double *, BLASLONG,BLASLONG,BLASLONG);
20572057

20582058
int sgemm_batch_thread(blas_arg_t * queue, BLASLONG nums);
20592059
int dgemm_batch_thread(blas_arg_t * queue, BLASLONG nums);

common_param.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,16 +1256,16 @@ int (*shgemv_t) (BLASLONG, BLASLONG, float, hfloat16 *, BLASLONG, hfloat16 *, BL
12561256
#endif
12571257

12581258
#if (BUILD_SINGLE==1)
1259-
int (*sgeadd_k) (BLASLONG, BLASLONG, float, float *, BLASLONG, float, float *, BLASLONG);
1259+
int (*sgeadd_k) (BLASLONG, BLASLONG, float, float *, BLASLONG, float, float *, BLASLONG, BLASLONG, BLASLONG);
12601260
#endif
12611261
#if (BUILD_DOUBLE==1)
1262-
int (*dgeadd_k) (BLASLONG, BLASLONG, double, double *, BLASLONG, double, double *, BLASLONG);
1262+
int (*dgeadd_k) (BLASLONG, BLASLONG, double, double *, BLASLONG, double, double *, BLASLONG, BLASLONG, BLASLONG);
12631263
#endif
12641264
#if (BUILD_COMPLEX==1)
1265-
int (*cgeadd_k) (BLASLONG, BLASLONG, float, float, float *, BLASLONG, float, float, float *, BLASLONG);
1265+
int (*cgeadd_k) (BLASLONG, BLASLONG, float, float, float *, BLASLONG, float, float, float *, BLASLONG, BLASLONG, BLASLONG);
12661266
#endif
12671267
#if (BUILD_COMPLEX16==1)
1268-
int (*zgeadd_k) (BLASLONG, BLASLONG, double, double, double *, BLASLONG, double, double, double *, BLASLONG);
1268+
int (*zgeadd_k) (BLASLONG, BLASLONG, double, double, double *, BLASLONG, double, double, double *, BLASLONG, BLASLONG, BLASLONG);
12691269
#endif
12701270
} gotoblas_t;
12711271

interface/geadd.c

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#ifndef CBLAS
5252

5353
void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
54-
FLOAT *BETA, FLOAT *c, blasint *LDC)
54+
FLOAT *BETA, FLOAT *c, blasint *LDC, char *TRANS_A,char *TRANS_C)
5555
{
5656

5757
blasint m = *M;
@@ -62,14 +62,31 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
6262
FLOAT beta = *BETA;
6363

6464
blasint info;
65+
char transa = (*TRANS_A == 'T') || (*TRANS_A == 't') || (*TRANS_A == 'C') || (*TRANS_A == 'c');
66+
char transc = (*TRANS_C == 'T') || (*TRANS_C == 't') || (*TRANS_C == 'C') || (*TRANS_C == 'c');
67+
6568

6669
PRINT_DEBUG_NAME;
6770

6871
info = 0;
72+
if(transa){
73+
if (lda < MAX(1, n))info = 5;
74+
75+
76+
} else{
77+
78+
if (lda < MAX(1, m)) info = 5;
79+
}
80+
6981

82+
if(transc){
83+
if (ldc < MAX(1, n)) info = 8;
7084

71-
if (lda < MAX(1, m)) info = 5;
72-
if (ldc < MAX(1, m)) info = 8;
85+
86+
}else{
87+
88+
if (ldc < MAX(1, m)) info = 8;
89+
}
7390

7491
if (n < 0) info = 2;
7592
if (m < 0) info = 1;
@@ -80,7 +97,7 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
8097
}
8198

8299
#else
83-
void CNAME( enum CBLAS_ORDER order, blasint m, blasint n, FLOAT alpha, FLOAT *a, blasint lda, FLOAT beta,
100+
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,
84101
FLOAT *c, blasint ldc)
85102
{
86103
/*
@@ -100,9 +117,17 @@ void CNAME(enum CBLAS_ORDER order,
100117
if (order == CblasColMajor) {
101118

102119
info = -1;
103-
104-
if (ldc < MAX(1, m)) info = 8;
105-
if (lda < MAX(1, m)) info = 5;
120+
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
121+
if (ldc < MAX(1, m)) info = 8;
122+
} else {
123+
if (ldc < MAX(1, n)) info = 8;
124+
}
125+
126+
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
127+
if (lda < MAX(1, m)) info = 5;
128+
} else {
129+
if (lda < MAX(1, n)) info = 5;
130+
}
106131
if (n < 0) info = 2;
107132
if (m < 0) info = 1;
108133

@@ -115,8 +140,17 @@ void CNAME(enum CBLAS_ORDER order,
115140
n = m;
116141
m = t;
117142

118-
if (ldc < MAX(1, m)) info = 8;
119-
if (lda < MAX(1, m)) info = 5;
143+
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
144+
if (ldc < MAX(1, m)) info = 8;
145+
} else {
146+
if (ldc < MAX(1, n)) info = 8;
147+
}
148+
149+
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
150+
if (lda < MAX(1, m)) info = 5;
151+
} else {
152+
if (lda < MAX(1, n)) info = 5;
153+
}
120154
if (n < 0) info = 1;
121155
if (m < 0) info = 2;
122156
}
@@ -136,7 +170,14 @@ void CNAME(enum CBLAS_ORDER order,
136170
FUNCTION_PROFILE_START();
137171

138172

139-
GEADD_K(m,n,alpha, a, lda, beta, c, ldc);
173+
GEADD_K(m,n,alpha, a, lda, beta, c, ldc,
174+
#ifdef CBLAS
175+
(transa == CblasTrans) || (transa == CblasConjTrans),
176+
(transc == CblasTrans) || (transc == CblasConjTrans)
177+
#else
178+
transa, transc
179+
#endif
180+
);
140181

141182

142183
FUNCTION_PROFILE_END(1, 2* m * n , 2 * m * n);

interface/zgeadd.c

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#ifndef CBLAS
5252

5353
void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
54-
FLOAT *BETA, FLOAT *c, blasint *LDC)
54+
FLOAT *BETA, FLOAT *c, blasint *LDC,char *TRANS_A,char *TRANS_C)
5555
{
5656

5757
blasint m = *M;
@@ -60,14 +60,34 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
6060
blasint ldc = *LDC;
6161

6262
blasint info;
63+
char transa = (*TRANS_A == 'T') || (*TRANS_A == 't') || (*TRANS_A == 'C') || (*TRANS_A == 'c');
64+
char transc = (*TRANS_C == 'T') || (*TRANS_C == 't') || (*TRANS_C == 'C') || (*TRANS_C == 'c');
65+
6366

6467
PRINT_DEBUG_NAME;
6568

6669
info = 0;
6770

6871

69-
if (lda < MAX(1, m)) info = 5;
70-
if (ldc < MAX(1, m)) info = 8;
72+
if(transa){
73+
if (lda < MAX(1, n))info = 5;
74+
75+
76+
} else{
77+
78+
if (lda < MAX(1, m)) info = 5;
79+
}
80+
81+
82+
if(transc){
83+
if (ldc < MAX(1, n)) info = 8;
84+
85+
86+
}else{
87+
88+
if (ldc < MAX(1, m)) info = 8;
89+
}
90+
7191

7292
if (n < 0) info = 2;
7393
if (m < 0) info = 1;
@@ -78,7 +98,7 @@ void NAME(blasint *M, blasint *N, FLOAT *ALPHA, FLOAT *a, blasint *LDA,
7898
}
7999

80100
#else
81-
void CNAME( enum CBLAS_ORDER order, blasint m, blasint n, FLOAT *ALPHA, FLOAT *a, blasint lda, FLOAT *BETA,
101+
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,
82102
FLOAT *c, blasint ldc)
83103
{
84104
/*
@@ -99,11 +119,19 @@ void CNAME(enum CBLAS_ORDER order,
99119

100120
info = -1;
101121

102-
if (ldc < MAX(1, m)) info = 8;
103-
if (lda < MAX(1, m)) info = 5;
122+
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
123+
if (ldc < MAX(1, m)) info = 8;
124+
} else {
125+
if (ldc < MAX(1, n)) info = 8;
126+
}
127+
128+
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
129+
if (lda < MAX(1, m)) info = 5;
130+
} else {
131+
if (lda < MAX(1, n)) info = 5;
132+
}
104133
if (n < 0) info = 2;
105-
if (m < 0) info = 1;
106-
134+
if (m < 0) info = 1;
107135
}
108136

109137
if (order == CblasRowMajor) {
@@ -112,13 +140,24 @@ void CNAME(enum CBLAS_ORDER order,
112140
t = n;
113141
n = m;
114142
m = t;
115-
116-
if (ldc < MAX(1, m)) info = 8;
117-
if (lda < MAX(1, m)) info = 5;
143+
if ( (transc == CblasNoTrans) || (transc == CblasConjNoTrans) ) {
144+
if (ldc < MAX(1, m)) info = 8;
145+
} else {
146+
if (ldc < MAX(1, n)) info = 8;
147+
}
148+
149+
if ( (transa == CblasNoTrans) || (transa == CblasConjNoTrans) ) {
150+
if (lda < MAX(1, m)) info = 5;
151+
} else {
152+
if (lda < MAX(1, n)) info = 5;
153+
}
118154
if (n < 0) info = 1;
119155
if (m < 0) info = 2;
120156
}
121157

158+
159+
160+
122161
if (info >= 0) {
123162
BLASFUNC(xerbla)(ERROR_NAME, &info, sizeof(ERROR_NAME));
124163
return;
@@ -134,7 +173,18 @@ void CNAME(enum CBLAS_ORDER order,
134173
FUNCTION_PROFILE_START();
135174

136175

137-
GEADD_K(m,n,ALPHA[0],ALPHA[1], a, lda, BETA[0], BETA[1], c, ldc);
176+
GEADD_K(m,n,ALPHA[0],ALPHA[1], a, lda, BETA[0], BETA[1], c, ldc,
177+
178+
#ifdef CBLAS
179+
(transa == CblasTrans) || (transa == CblasConjTrans),
180+
(transc == CblasTrans) || (transc == CblasConjTrans)
181+
#else
182+
transa, transc
183+
#endif
184+
);
185+
186+
187+
138188

139189

140190
FUNCTION_PROFILE_END(1, 2* m * n , 2 * m * n);

0 commit comments

Comments
 (0)