Skip to content

Commit fffbf73

Browse files
ShabiShett07kgryte
andauthored
feat: add C implementation for blas/base/dsyr
PR-URL: #6566 Ref: #2039 Co-authored-by: Athan Reines <kgryte@gmail.com> Reviewed-by: Athan Reines <kgryte@gmail.com>
1 parent 260a8ca commit fffbf73

30 files changed

+3523
-57
lines changed

lib/node_modules/@stdlib/blas/base/dsyr/README.md

Lines changed: 115 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ Performs the symmetric rank 1 operation `A = α*x*x^T + A` where `α` is a scala
3737
```javascript
3838
var Float64Array = require( '@stdlib/array/float64' );
3939

40-
var A = new Float64Array( [ 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 0.0, 0.0, 1.0 ] );
40+
var A = new Float64Array( [ 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 ] );
4141
var x = new Float64Array( [ 1.0, 2.0, 3.0 ] );
4242

4343
dsyr( 'row-major', 'upper', 3, 1.0, x, 1, A, 3 );
44-
// A => <Float64Array>[ 2.0, 4.0, 6.0, 0.0, 5.0, 8.0, 0.0, 0.0, 10.0 ]
44+
// A => <Float64Array>[ 2.0, 4.0, 6.0, 2.0, 5.0, 8.0, 3.0, 2.0, 10.0 ]
4545
```
4646

4747
The function has the following parameters:
@@ -51,20 +51,20 @@ The function has the following parameters:
5151
- **N**: number of elements along each dimension of `A`.
5252
- **α**: scalar constant.
5353
- **x**: input [`Float64Array`][mdn-float64array].
54-
- **sx**: index increment for `x`.
54+
- **sx**: stride length for `x`.
5555
- **A**: input matrix stored in linear memory as a [`Float64Array`][mdn-float64array].
5656
- **lda**: stride of the first dimension of `A` (a.k.a., leading dimension of the matrix `A`).
5757

58-
The stride parameters determine how elements in the input arrays are accessed at runtime. For example, to iterate over every other element of `x` in reverse order,
58+
The stride parameters determine how elements in the input arrays are accessed at runtime. For example, to iterate over the elements of `x` in reverse order,
5959

6060
```javascript
6161
var Float64Array = require( '@stdlib/array/float64' );
6262

63-
var A = new Float64Array( [ 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 0.0, 0.0, 1.0 ] );
64-
var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] );
63+
var A = new Float64Array( [ 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 ] );
64+
var x = new Float64Array( [ 3.0, 2.0, 1.0 ] );
6565

66-
dsyr( 'row-major', 'upper', 3, 1.0, x, -2, A, 3 );
67-
// A => <Float64Array>[ 26.0, 17.0, 8.0, 0.0, 10.0, 5.0, 0.0, 0.0, 2.0 ]
66+
dsyr( 'row-major', 'upper', 3, 1.0, x, -1, A, 3 );
67+
// A => <Float64Array>[ 2.0, 4.0, 6.0, 2.0, 5.0, 8.0, 3.0, 2.0, 10.0 ]
6868
```
6969

7070
Note that indexing is relative to the first index. To introduce an offset, use [`typed array`][mdn-typed-array] views.
@@ -75,14 +75,14 @@ Note that indexing is relative to the first index. To introduce an offset, use [
7575
var Float64Array = require( '@stdlib/array/float64' );
7676

7777
// Initial arrays...
78-
var x0 = new Float64Array( [ 1.0, 1.0, 1.0, 1.0 ] );
79-
var A = new Float64Array( [ 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 0.0, 0.0, 1.0 ] );
78+
var x0 = new Float64Array( [ 0.0, 3.0, 2.0, 1.0 ] );
79+
var A = new Float64Array( [ 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 ] );
8080

8181
// Create offset views...
8282
var x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
8383

8484
dsyr( 'row-major', 'upper', 3, 1.0, x1, -1, A, 3 );
85-
// A => <Float64Array>[ 2.0, 3.0, 4.0, 0.0, 2.0, 3.0, 0.0, 0.0, 2.0 ]
85+
// A => <Float64Array>[ 2.0, 4.0, 6.0, 2.0, 5.0, 8.0, 3.0, 2.0, 10.0 ]
8686
```
8787

8888
#### dsyr.ndarray( uplo, N, α, x, sx, ox, A, sa1, sa2, oa )
@@ -92,11 +92,11 @@ Performs the symmetric rank 1 operation `A = α*x*x^T + A`, using alternative in
9292
```javascript
9393
var Float64Array = require( '@stdlib/array/float64' );
9494

95-
var A = new Float64Array( [ 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 0.0, 0.0, 1.0 ] );
95+
var A = new Float64Array( [ 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 ] );
9696
var x = new Float64Array( [ 1.0, 2.0, 3.0 ] );
9797

9898
dsyr.ndarray( 'upper', 3, 1.0, x, 1, 0, A, 3, 1, 0 );
99-
// A => <Float64Array>[ 2.0, 4.0, 6.0, 0.0, 5.0, 8.0, 0.0, 0.0, 10.0 ]
99+
// A => <Float64Array>[ 2.0, 4.0, 6.0, 2.0, 5.0, 8.0, 3.0, 2.0, 10.0 ]
100100
```
101101

102102
The function has the following additional parameters:
@@ -111,11 +111,11 @@ While [`typed array`][mdn-typed-array] views mandate a view offset based on the
111111
```javascript
112112
var Float64Array = require( '@stdlib/array/float64' );
113113

114-
var A = new Float64Array( [ 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 0.0, 0.0, 1.0 ] );
114+
var A = new Float64Array( [ 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 ] );
115115
var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] );
116116

117117
dsyr.ndarray( 'upper', 3, 1.0, x, -2, 4, A, 3, 1, 0 );
118-
// A => <Float64Array>[ 26.0, 17.0, 8.0, 0.0, 10.0, 5.0, 0.0, 0.0, 2.0 ]
118+
// A => <Float64Array>[ 26.0, 17.0, 8.0, 2.0, 10.0, 5.0, 3.0, 2.0, 2.0 ]
119119
```
120120

121121
</section>
@@ -149,11 +149,18 @@ var opts = {
149149

150150
var N = 3;
151151

152-
var A = ones( N*N, opts.dtype );
152+
// Create N-by-N symmetric matrices:
153+
var A1 = ones( N*N, opts.dtype );
154+
var A2 = ones( N*N, opts.dtype );
155+
156+
// Create a random vector:
153157
var x = discreteUniform( N, -10.0, 10.0, opts );
154158

155-
dsyr( 'row-major', 'upper', 3, 1.0, x, 1, A, 3 );
156-
console.log( A );
159+
dsyr( 'row-major', 'upper', 3, 1.0, x, 1, A1, 3 );
160+
console.log( A1 );
161+
162+
dsyr.ndarray( 'upper', 3, 1.0, x, 1, 0, A2, 3, 1, 0 );
163+
console.log( A2 );
157164
```
158165

159166
</section>
@@ -183,21 +190,65 @@ console.log( A );
183190
### Usage
184191

185192
```c
186-
TODO
193+
#include "stdlib/blas/base/dsyr.h"
187194
```
188195

189-
#### TODO
196+
#### c_dsyr( layout, uplo, N, alpha, \*X, sx, \*A, LDA )
190197

191-
TODO.
198+
Performs the symmetric rank 1 operation `A = α*x*x^T + A` where `α` is a scalar, `x` is an `N` element vector, and `A` is an `N` by `N` symmetric matrix.
192199

193200
```c
194-
TODO
201+
#include "stdlib/blas/base/shared.h"
202+
203+
double A[] = { 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 };
204+
const double x[] = { 1.0, 2.0, 3.0 };
205+
206+
c_dsyr( CblasColMajor, CblasUpper, 3, 1.0, x, 1, A, 3 );
195207
```
196208
197-
TODO
209+
The function accepts the following arguments:
210+
211+
- **layout**: `[in] CBLAS_LAYOUT` storage layout.
212+
- **uplo**: `[in] CBLAS_UPLO` specifies whether the upper or lower triangular part of the symmetric matrix `A` should be referenced.
213+
- **N**: `[in] CBLAS_INT` number of elements along each dimension of `A`.
214+
- **alpha**: `[in] double` scalar constant.
215+
- **X**: `[in] double*` input array.
216+
- **sx**: `[in] CBLAS_INT` stride length for `X`.
217+
- **A**: `[inout] double*` input matrix.
218+
- **LDA**: `[in] CBLAS_INT` stride of the first dimension of `A` (a.k.a., leading dimension of the matrix `A`).
219+
220+
```c
221+
void c_dsyr( const CBLAS_LAYOUT layout, const CBLAS_UPLO uplo, const CBLAS_INT N, const double alpha, const double *X, const CBLAS_INT strideX, double *A, const CBLAS_INT LDA )
222+
```
223+
224+
#### c_dsyr_ndarray( uplo, N, alpha, \*X, sx, ox, \*A, sa1, sa2, oa )
225+
226+
Performs the symmetric rank 1 operation `A = α*x*x^T + A`, using alternative indexing semantics and where `α` is a scalar, `x` is an `N` element vector, and `A` is an `N` by `N` symmetric matrix.
227+
228+
```c
229+
#include "stdlib/blas/base/shared.h"
230+
231+
double A[] = { 1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0 };
232+
const double x[] = { 1.0, 2.0, 3.0 };
233+
234+
c_dsyr_ndarray( CblasUpper, 3, 1.0, x, 1, 0, A, 3, 1, 0 );
235+
```
236+
237+
The function accepts the following arguments:
238+
239+
- **uplo**: `[in] CBLAS_UPLO` specifies whether the upper or lower triangular part of the symmetric matrix `A` should be referenced.
240+
- **N**: `[in] CBLAS_INT` number of elements along each dimension of `A`.
241+
- **alpha**: `[in] double` scalar constant.
242+
- **X**: `[in] double*` input array.
243+
- **sx**: `[in] CBLAS_INT` stride length for `X`.
244+
- **ox**: `[in] CBLAS_INT` starting index for `X`.
245+
- **A**: `[inout] double*` input matrix.
246+
- **sa1**: `[in] CBLAS_INT` stride of the first dimension of `A`.
247+
- **sa2**: `[in] CBLAS_INT` stride of the second dimension of `A`.
248+
- **oa**: `[in] CBLAS_INT` starting index for `A`.
198249
199250
```c
200-
TODO
251+
void c_dsyr_ndarray( const CBLAS_UPLO uplo, const CBLAS_INT N, const double alpha, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, double *A, const CBLAS_INT strideA1, const CBLAS_INT strideA2, const CBLAS_INT offsetA )
201252
```
202253

203254
</section>
@@ -219,7 +270,46 @@ TODO
219270
### Examples
220271

221272
```c
222-
TODO
273+
#include "stdlib/blas/base/dsyr.h"
274+
#include "stdlib/blas/base/shared.h"
275+
#include <stdio.h>
276+
277+
int main( void ) {
278+
// Define 3x3 symmetric matrices stored in row-major layout:
279+
double A1[ 3*3 ] = {
280+
1.0, 2.0, 3.0,
281+
2.0, 1.0, 2.0,
282+
3.0, 2.0, 1.0
283+
};
284+
285+
double A2[ 3*3 ] = {
286+
1.0, 2.0, 3.0,
287+
2.0, 1.0, 2.0,
288+
3.0, 2.0, 1.0
289+
};
290+
291+
// Define a vector:
292+
const double x[ 3 ] = { 1.0, 2.0, 3.0 };
293+
294+
// Specify the number of elements along each dimension of `A1` and `A2`:
295+
const int N = 3;
296+
297+
// Perform the symmetric rank 1 operation `A = α*x*x^T + A`:
298+
c_dsyr( CblasColMajor, CblasUpper, N, 1.0, x, 1, A1, N );
299+
300+
// Print the result:
301+
for ( int i = 0; i < N*N; i++ ) {
302+
printf( "A1[ %i ] = %f\n", i, A1[ i ] );
303+
}
304+
305+
// Perform the symmetric rank 1 operation `A = α*x*x^T + A` using alternative indexing semantics:
306+
c_dsyr_ndarray( CblasUpper, N, 1.0, x, 1, 0, A2, N, 1, 0 );
307+
308+
// Print the result:
309+
for ( int i = 0; i < N*N; i++ ) {
310+
printf( "A2[ %i ] = %f\n", i, A[ i ] );
311+
}
312+
}
223313
```
224314
225315
</section>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var resolve = require( 'path' ).resolve;
24+
var bench = require( '@stdlib/bench' );
25+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
26+
var ones = require( '@stdlib/array/ones' );
27+
var pow = require( '@stdlib/math/base/special/pow' );
28+
var floor = require( '@stdlib/math/base/special/floor' );
29+
var tryRequire = require( '@stdlib/utils/try-require' );
30+
var pkg = require( './../package.json' ).name;
31+
32+
33+
// VARIABLES //
34+
35+
var dsyr = tryRequire( resolve( __dirname, './../lib/dsyr.native.js' ) );
36+
var opts = {
37+
'skip': ( dsyr instanceof Error )
38+
};
39+
var options = {
40+
'dtype': 'float64'
41+
};
42+
43+
44+
// FUNCTIONS //
45+
46+
/**
47+
* Creates a benchmark function.
48+
*
49+
* @private
50+
* @param {PositiveInteger} N - number of elements along each dimension
51+
* @returns {Function} benchmark function
52+
*/
53+
function createBenchmark( N ) {
54+
var x = ones( N, options.dtype );
55+
var A = ones( N*N, options.dtype );
56+
return benchmark;
57+
58+
/**
59+
* Benchmark function.
60+
*
61+
* @private
62+
* @param {Benchmark} b - benchmark instance
63+
*/
64+
function benchmark( b ) {
65+
var z;
66+
var i;
67+
68+
b.tic();
69+
for ( i = 0; i < b.iterations; i++ ) {
70+
z = dsyr( 'row-major', 'upper', N, 1.0, x, 1, A, N );
71+
if ( isnan( z[ i%z.length ] ) ) {
72+
b.fail( 'should not return NaN' );
73+
}
74+
}
75+
b.toc();
76+
if ( isnan( z[ i%z.length ] ) ) {
77+
b.fail( 'should not return NaN' );
78+
}
79+
b.pass( 'benchmark finished' );
80+
b.end();
81+
}
82+
}
83+
84+
85+
// MAIN //
86+
87+
/**
88+
* Main execution sequence.
89+
*
90+
* @private
91+
*/
92+
function main() {
93+
var min;
94+
var max;
95+
var N;
96+
var f;
97+
var i;
98+
99+
min = 1; // 10^min
100+
max = 6; // 10^max
101+
102+
for ( i = min; i <= max; i++ ) {
103+
N = floor( pow( pow( 10, i ), 1.0/2.0 ) );
104+
f = createBenchmark( N );
105+
bench( pkg+'::native:size='+(N*N), opts, f );
106+
}
107+
}
108+
109+
main();

0 commit comments

Comments
 (0)