8000 feat: add c implementation for `blas/base/sgemv` by ShabiShett07 · Pull Request #6984 · stdlib-js/stdlib · GitHub
[go: up one dir, main page]

Skip to content

feat: add c implementation for blas/base/sgemv #6984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 4, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: add implementation
---
type: pre_commit_static_analysis_report
description: Results of running static analysis checks when committing changes.
report:
  - task: lint_filenames
    status: passed
  - task: lint_editorconfig
    status: passed
  - task: lint_markdown
    status: passed
  - task: lint_package_json
    status: na
  - task: lint_repl_help
    status: na
  - task: lint_javascript_src
    status: passed
  - task: lint_javascript_cli
    status: na
  - task: lint_javascript_examples
    status: passed
  - task: lint_javascript_tests
    status: passed
  - task: lint_javascript_benchmarks
    status: na
  - task: lint_python
    status: na
  - task: lint_r
    status: na
  - task: lint_c_src
    status: missing_dependencies
  - task: lint_c_examples
    status: missing_dependencies
  - task: lint_c_benchmarks
    status: na
  - task: lint_c_tests_fixtures
    status: na
  - task: lint_shell
    status: na
  - task: lint_typescript_declarations
    status: na
  - task: lint_typescript_tests
    status: na
  - task: lint_license_headers
    status: passed
---
  • Loading branch information
ShabiShett07 committed May 16, 2025
commit f90d065a86a6466d3caa11f68bcb6376be8ec06c
98 changes: 92 additions & 6 deletions lib/node_modules/@stdlib/blas/base/sgemv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ sgemv( 'row-major', 'no-transpose', 2, 2, 1.0, A, 2, x1, -1, 1.0, y1, -1 );
// y0 => <Float32Array>[ 0.0, 8.0, 4.0 ]
```

<!-- lint disable maximum-heading-length -->

#### sgemv.ndarray( trans, M, N, α, A, sa1, sa2, oa, x, sx, ox, β, y, sy, oy )

Performs one of the matrix-vector operations `y = α*A*x + β*y` or `y = α*A^T*x + β*y`, using alternative indexing semantics and where `α` and `β` are scalars, `x` and `y` are vectors, and `A` is an `M` by `N` matrix.
Expand Down Expand Up @@ -199,18 +201,73 @@ console.log( y );
#include "stdlib/blas/base/sgemv.h"
```

#### TODO
#### c_sgemv( order, trans, M, N, alpha, \*A, LDA, \*X, strideX, beta, \*Y, strideY )

Performs one of the matrix-vector operations `y = α*A*x + β*y` or `y = α*A^T*x + β*y`, where `α` and `β` are scalars, `x` and `y` are vectors, and `A` is an `M` by `N` matrix.

```c
#include "stdlib/blas/base/shared.h"

float A[] = { 1.0f, 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 3.0f, 2.0f, 1.0f };
const float x[] = { 1.0f, 2.0f, 3.0f };
const float y[] = { 1.0f, 2.0f, 3.0f };

c_sgemv( CblasColMajor, CblasNoTrans, 3, 3, 1.0f, A, 3, x, 1, 1.0f, y, 1 );
```

The function accepts the following arguments:

- **order**: `[in] CBLAS_LAYOUT` storage layout.
- **trans**: `[in] CBLAS_TRANSPOSE` specifies whether `A` should be transposed, conjugate-transposed, or not transposed.
- **M**: `[in] CBLAS_INT` number of rows in the matrix `A`.
- **N**: `[in] CBLAS_INT` number of columns in the matrix `A`.
- **alpha**: `[in] float` scalar.
- **A**: `[inout] float*` input matrix.
- **LDA**: `[in] CBLAS_INT` stride of the first dimension of `A` (a.k.a., leading dimension of the matrix `A`).
- **X**: `[in] float*` first input vector.
- **strideX**: `[in] CBLAS_INT` index increment for `X`.
- **beta**: `[in] float` scalar.
- **Y**: `[in] float*` second input vector.
- **strideY**: `[in] CBLAS_INT` index increment for `Y`.

```c
void c_sgemv( const CBLAS_LAYOUT order, const CBLAS_TRANSPOSE trans, const CBLAS_INT M, const CBLAS_INT N, const float alpha, const float *A, const CBLAS_INT LDA, const float *x, const CBLAS_INT strideX, const float beta, float *y, const CBLAS_INT strideY )
```

#### c_sgemv_ndarray( trans, M, N, alpha, \*A, sa1, sa2, oa, \*X, sx, ox, beta, \*Y, sy, oy )

TODO.
Performs one of the matrix-vector operations `y = α*A*x + β*y` or `y = α*A^T*x + β*y`, where `α` and `β` are scalars, `x` and `y` are vectors, and `A` is an `M` by `N` matrix using indexing alternative semantics.

```c
TODO
#include "stdlib/blas/base/shared.h"

float A[] = { 1.0f, 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 3.0f, 2.0f, 1.0f };
const float x[] = { 1.0f, 2.0f, 3.0f };
const float y[] = { 1.0f, 2.0f, 3.0f };

c_sgemv_ndarray( CblasNoTrans, 3, 3, 1.0f, A, 1, 3, 0, x, 1, 0, 1.0f, y, 1, 0 );
```

TODO
The function accepts the following arguments:

- **trans**: `[in] CBLAS_TRANSPOSE` specifies whether `A` should be transposed, conjugate-transposed, or not transposed.
- **M**: `[in] CBLAS_INT` number of rows in the matrix `A`.
- **N**: `[in] CBLAS_INT` number of columns in the matrix `A`.
- **alpha**: `[in] float` scalar.
- **A**: `[inout] float*` input matrix.
- **sa1**: `[in] CBLAS_INT` stride of the first dimension of `A`.
- **sa2**: `[in] CBLAS_INT` stride of the second dimension of `A`.
- **oa**: `[in] CBLAS_INT` starting index for `A`.
- **X**: `[in] float*` first input vector.
- **strideX**: `[in] CBLAS_INT` index increment for `X`.
- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
- **beta**: `[in] float` scalar.
- **Y**: `[in] float*` second input vector.
- **strideY**: `[in] CBLAS_INT` index increment for `Y`.
- **offsetY**: `[in] CBLAS_INT` starting index for `Y`.

```c
TODO
void c_sgemv_ndarray( const CBLAS_TRANSPOSE trans, const CBLAS_INT M, const CBLAS_INT N, const float alpha, const float *A, const CBLAS_INT strideA1, const CBLAS_INT strideA2, const CBLAS_INT offsetA, const float *x, const CBLAS_INT strideX, const CBLAS_INT offsetX, const float beta, float *y, const CBLAS_INT strideY, const CBLAS_INT offsetY )
```

</section>
Expand All @@ -232,7 +289,36 @@ TODO
### Examples

```c
TODO
#include "stdlib/blas/base/sgemv.h"
#include "stdlib/blas/base/shared.h"
#include <stdio.h>

int main( void ) {
// Create a strided array:
const float A[] = { 1.0f, 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 3.0f, 2.0f, 1.0f };
const float x[] = { 1.0f, 2.0f, 3.0f };
float y[] = { 1.0f, 2.0f, 3.0f };

// Specify the number of elements along each dimension of `A`:
const int M = 3;
const int N = 3;

// Perform the matrix-vector operations `y = α*A*x + β*y`:
c_sgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0f, A, M, x, 1, 1.0f, y, 1 );

// Print the result:
for ( int i = 0; i < N; i++ ) {
printf( "y[ %i ] = %f\n", i, y[ i ] );
}

// Perform the symmetric rank 2 operation `A = α*x*y^T + α*y*x^T + A`:
c_sgemv_ndarray( CblasNoTrans, 3, 3, 1.0f, A, 3, 1, 0, x, 1, 0, 1.0f, y, 1, 0 );

// Print the result:
for ( int i = 0; i < N; i++ ) {
printf( "y[ %i ] = %f\n", i, y[ i ] );
}
}
```

</section>
Expand Down
4 changes: 2 additions & 2 deletions lib/node_modules/@stdlib/blas/base/sgemv/examples/c/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ int main( void ) {
const int N = 3;

// Perform the matrix-vector operations `y = α*A*x + β*y`:
c_sgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0f, A, 1, x, 1, 1.0f, y, 1 );
c_sgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0f, A, M, x, 1, 1.0f, y, 1 );

// Print the result:
for ( int i = 0; i < N; i++ ) {
printf( "y[ %i ] = %f\n", i, y[ i ] );
}

// Perform the symmetric rank 2 operation `A = α*x*y^T + α*y*x^T + A`:
c_sgemv_ndarray( CblasNoTrans, M, N, 1.0f, A, 1, 1, 0, x, 1, 0, 1.0f, y, 1, 0 );
c_sgemv_ndarray( CblasNoTrans, 3, 3, 1.0f, A, 3, 1, 0, x, 1, 0, 1.0f, y, 1, 0 );

// Print the result:
for ( int i = 0; i < N; i++ ) {
Expand Down
5 changes: 4 additions & 1 deletion lib/node_modules/@stdlib/blas/base/sgemv/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@ var A = discreteUniform( M*N, 0, 255, opts );
var x = discreteUniform( N, 0, 255, opts );
var y = discreteUniform( M, 0, 255, opts );

sgemv( 'row-major', 'no-transpose', M, N, 1.0, A, N, x, -1, 1.0, y, -1 );
sgemv( 'row-major', 'no-transpose', M, N, 1.0, A, N, x, 1, 1.0, y, 1 );
console.log( y );

sgemv.ndarray( 'no-transpose', M, N, 1.0, A, N, 1, 0, x, 1, 0, 1.0, y, 1, 0 );
console.log( y );
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ var addon = require( './../src/addon.node' );
*
* var A = new Float32Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
* var x = new Float32Array( [ 1.0, 1.0, 1.0 ] );
* var y = new Float32Array( [ 1.0, 1.0, 1.0 ] );
* var y = new Float32Array( [ 1.0, 1.0 ] );
*
* sgemv( 'no-transpose', 2, 3, 1.0, A, 3, 1, 0, x, 1, 0, 1.0, y, 1, 0 );
* // y => <Float32Array>[ 6.0, 8.0, 1.0 ]
* // y => <Float32Array>[ 7.0, 16.0 ]
*/
function sgemv( trans, M, N, alpha, A, strideA1, strideA2, offsetA, x, strideX, offsetX, beta, y, strideY, offsetY ) { // eslint-disable-line max-params, max-len
return addon.ndarray( resolveTrans( trans ), M, N, alpha, A, strideA1, strideA2, offsetA, x, strideX, offsetX, beta, y, strideY, offsetY ); // eslint-disable-line max-len
addon.ndarray( resolveTrans( trans ), M, N, alpha, A, strideA1, strideA2, offsetA, x, strideX, offsetX, beta, y, strideY, offsetY ); // eslint-disable-line max-len
return y;
}


Expand Down
7 changes: 4 additions & 3 deletions lib/node_modules/@stdlib/blas/base/sgemv/lib/sgemv.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ var addon = require( './../src/addon.node' );
*
* var A = new Float32Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
* var x = new Float32Array( [ 1.0, 1.0, 1.0 ] );
* var y = new Float32Array( [ 1.0, 1.0, 1.0 ] );
* var y = new Float32Array( [ 1.0, 1.0 ] );
*
* sgemv( 'row-major', 'no-transpose', 2, 3, 1.0, A, 3, x, 1, 1.0, y, 1 );
* // y => <Float32Array>[ 6.0, 8.0, 1.0 ]
* // y => <Float32Array>[ 7.0, 16.0 ]
*/
function sgemv( order, trans, M, N, alpha, A, LDA, x, strideX, beta, y, strideY ) { // eslint-disable-line max-params, max-len
return addon( resolveOrder( order ), resolveTrans( trans ), M, N, alpha, A, LDA, x, strideX, beta, y, strideY ); // eslint-disable-line max-len
addon( resolveOrder( order ), resolveTrans( trans ), M, N, alpha, A, LDA, x, strideX, beta, y, strideY ); // eslint-disable-line max-len
return y;
}


Expand Down
41 changes: 36 additions & 5 deletions lib/node_modules/@stdlib/blas/base/sgemv/src/addon.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,29 @@ static napi_value addon( napi_env env, napi_callback_info info ) {
STDLIB_NAPI_ARGV_FLOAT( env, alpha, argv, 4 );
STDLIB_NAPI_ARGV_FLOAT( env, beta, argv, 9 );

STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, X, N, strideX, argv, 7 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, Y, N, strideY, argv, 10 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY2D( env, A, M, N, LDA, 1, argv, 5 );
CBLAS_INT xlen;
CBLAS_INT ylen;
CBLAS_INT sa1;
CBLAS_INT sa2;

if ( trans == CblasNoTrans ) {
xlen = N;
ylen = M;
} else {
xlen = M;
ylen = N;
}
if ( order == CblasColMajor ) {
sa1 = 1;
sa2 = LDA;
} else { // order === 'row-major'
sa1 = LDA;
sa2 = 1;
}

STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, X, xlen, strideX, argv, 7 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, Y, ylen, strideY, argv, 10 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY2D( env, A, M, N, sa1, sa2, argv, 5 );

API_SUFFIX(c_sgemv)( order, trans, M, N, alpha, A, LDA, X, strideX, beta, Y, strideY );

Expand Down Expand Up @@ -83,8 +103,19 @@ static napi_value addon_method( napi_env env, napi_callback_info info ) {
STDLIB_NAPI_ARGV_FLOAT( env, alpha, argv, 3 );
STDLIB_NAPI_ARGV_FLOAT( env, beta, argv, 11 );

STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, X, N, strideX, argv, 8 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, Y, N, strideY, argv, 12 );
CBLAS_INT xlen;
CBLAS_INT ylen;

if ( trans == CblasNoTrans ) {
xlen = N;
ylen = M;
} else {
xlen = M;
ylen = N;
}

STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, X, xlen, strideX, argv, 8 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY( env, Y, ylen, strideY, argv, 12 );
STDLIB_NAPI_ARGV_STRIDED_FLOAT32ARRAY2D( env, A, M, N, strideA1, strideA2, argv, 4 );

API_SUFFIX(c_sgemv_ndarray)( trans, M, N, alpha, A, strideA1, strideA2, offsetA, X, strideX, offsetX, beta, Y, strideY, offsetY );
Expand Down
14 changes: 10 additions & 4 deletions lib/node_modules/@stdlib/blas/base/sgemv/src/sgemv.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@
* @return output value
*/
void API_SUFFIX(c_sgemv)( const CBLAS_LAYOUT order, const CBLAS_TRANSPOSE trans, const CBLAS_INT M, const CBLAS_INT N, const float alpha, const float *A, const CBLAS_INT LDA, const float *x, const CBLAS_INT strideX, const float beta, float *y, const CBLAS_INT strideY ) {
CBLAS_INT xlen;
CBLAS_INT ylen;
CBLAS_INT sa1;
CBLAS_INT sa2;
CBLAS_INT ox;
CBLAS_INT oy;

if ( M == 0 || N == 0 || ( alpha == 0.0f && beta == 1.0f ) ) {
return;
if ( trans == CblasNoTrans ) {
xlen = N;
ylen = M;
} else {
xlen = M;
ylen = N;
}
if ( order == CblasColMajor ) {
sa1 = 1;
Expand All @@ -53,8 +59,8 @@ void API_SUFFIX(c_sgemv)( const CBLAS_LAYOUT order, const CBLAS_TRANSPOSE trans,
sa1 = LDA;
sa2 = 1;
}
ox = stdlib_strided_stride2offset( N, strideX );
oy = stdlib_strided_stride2offset( N, strideY );
ox = stdlib_strided_stride2offset( xlen, strideX );
oy = stdlib_strided_stride2offset( ylen, strideY );
API_SUFFIX(c_sgemv_ndarray)( trans, M, N, alpha, A, sa1, sa2, 0, x, strideX, ox, beta, y, strideY, oy );
return;
}
33 changes: 15 additions & 18 deletions lib/node_modules/@stdlib/blas/base/sgemv/src/sgemv_ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,27 @@ void API_SUFFIX(c_sgemv_ndarray)( const CBLAS_TRANSPOSE trans, const CBLAS_INT M
// Note on variable naming convention: sa#, ix#, i# where # corresponds to the loop number, with `0` being the innermost loop...

int64_t strides[] = { strideA1, strideA2 };
isrm = stdlib_ndarray_is_row_major( 2, strides );
if ( M == 0 || N == 0 || ( alpha == 0.0f && beta == 1.0f ) ) {
return;
}
isrm = stdlib_ndarray_is_row_major( 2, strides );
if ( isrm ) {
// For row-major matrices, the last dimension has the fastest changing index...
sa0 = strideA2; // stride for innermost loop
sa1 = strideA1; // stride for outermost loop
} else { // isColMajor
// For column-major matrices, the first dimension has the fastest changing index...
sa0 = strideA1; // stride for innermost loop
sa1 = strideA2; // stride for outermost loop
sa0 = strideA2;
sa1 = strideA1;
} else {
sa0 = strideA1;
sa1 = strideA2;
}
if ( CblasNoTrans ) {

if ( trans == CblasNoTrans ) {
xlen = N;
ylen = M;
} else {
xlen = M;
ylen = N;
}
// y = beta*y

// y = beta * y
if ( beta != 1.0f ) {
if ( beta == 0.0f ) {
stdlib_strided_sfill_ndarray( ylen, 0.0f, y, strideY, offsetY );
Expand All @@ -90,17 +90,14 @@ void API_SUFFIX(c_sgemv_ndarray)( const CBLAS_TRANSPOSE trans, const CBLAS_INT M
return;
}
// Form: y = α*A*x + y
if (
( isrm && CblasNoTrans ) ||
( !isrm && CblasTrans )
) {
if ( ( !isrm && trans == CblasNoTrans ) || ( isrm && trans != CblasNoTrans ) ) {
ix1 = offsetX;
for ( i1 = 0; i1 < xlen; i1++ ) {
tmp = alpha * x[ ix1 ];
oa = offsetA + (sa1*i1);
oa = offsetA + sa1 * i1;
iy1 = offsetY;
for ( i0 = 0; i0 < ylen; i0++ ) {
y[ iy1 ] += A[ oa+(sa0*i0) ] * tmp;
y[ iy1 ] += A[ oa + sa0 * i0 ] * tmp;
iy1 += strideY;
}
ix1 += strideX;
Expand All @@ -114,9 +111,9 @@ void API_SUFFIX(c_sgemv_ndarray)( const CBLAS_TRANSPOSE trans, const CBLAS_INT M
for ( i1 = 0; i1 < ylen; i1++ ) {
tmp = 0.0f;
ix1 = offsetX;
oa = offsetA + (sa1*i1);
oa = offsetA + sa1 * i1;
for ( i0 = 0; i0 < xlen; i0++ ) {
tmp += A[ oa+(sa0*i0) ] * x[ ix1 ];
tmp += A[ oa + sa0 * i0 ] * x[ ix1 ];
ix1 += strideX;
}
y[ iy1 ] += alpha * tmp;
Expand Down
Loading
Loading
0