Skip to content

Commit f42098f

Browse files
aman-095kgrytestdlib-bot
authored andcommitted
feat: add C ndarray implementation for blas/base/zscal
PR-URL: stdlib-js#4864 Ref: stdlib-js#2039 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]> Co-authored-by: stdlib-bot <[email protected]>
1 parent 34145fc commit f42098f

24 files changed

+885
-664
lines changed

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

+85-52
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
@license Apache-2.0
44
5-
Copyright (c) 2024 The Stdlib Authors.
5+
Copyright (c) 2025 The Stdlib Authors.
66
77
Licensed under the Apache License, Version 2.0 (the "License");
88
you may not use this file except in compliance with the License.
@@ -30,39 +30,39 @@ limitations under the License.
3030
var zscal = require( '@stdlib/blas/base/zscal' );
3131
```
3232

33-
#### zscal( N, za, zx, strideX )
33+
#### zscal( N, alpha, x, strideX )
3434

35-
Scales values from `zx` by `za`.
35+
Scales values from `x` by `alpha`.
3636

3737
```javascript
3838
var Complex128Array = require( '@stdlib/array/complex128' );
3939
var Complex128 = require( '@stdlib/complex/float64/ctor' );
4040

41-
var zx = new Complex128Array( [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ] );
42-
var za = new Complex128( 2.0, 0.0 );
41+
var x = new Complex128Array( [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ] );
42+
var alpha = new Complex128( 2.0, 0.0 );
4343

44-
zscal( 3, za, zx, 1 );
45-
// zx => <Complex128Array>[ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 ]
44+
zscal( 3, alpha, x, 1 );
45+
// x => <Complex128Array>[ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 ]
4646
```
4747

4848
The function has the following parameters:
4949

5050
- **N**: number of indexed elements.
51-
- **za**: scalar [`Complex128`][@stdlib/complex/float64/ctor] constant.
52-
- **zx**: input [`Complex128Array`][@stdlib/array/complex128].
53-
- **strideX**: index increment for `zx`.
51+
- **alpha**: scalar [`Complex128`][@stdlib/complex/float64/ctor] constant.
52+
- **x**: input [`Complex128Array`][@stdlib/array/complex128].
53+
- **strideX**: index increment for `x`.
5454

55-
The `N` and stride parameters determine how values from `zx` are scaled by `za`. For example, to scale every other value in `zx` by `za`,
55+
The `N` and stride parameters determine how values from `x` are scaled by `alpha`. For example, to scale every other value in `x` by `alpha`,
5656

5757
```javascript
5858
var Complex128Array = require( '@stdlib/array/complex128' );
5959
var Complex128 = require( '@stdlib/complex/float64/ctor' );
6060

61-
var zx = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
62-
var za = new Complex128( 2.0, 0.0 );
61+
var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
62+
var alpha = new Complex128( 2.0, 0.0 );
6363

64-
zscal( 2, za, zx, 2 );
65-
// zx => <Complex128Array>[ 2.0, 4.0, 3.0, 4.0, 10.0, 12.0, 7.0, 8.0 ]
64+
zscal( 2, alpha, x, 2 );
65+
// x => <Complex128Array>[ 2.0, 4.0, 3.0, 4.0, 10.0, 12.0, 7.0, 8.0 ]
6666
```
6767

6868
Note that indexing is relative to the first index. To introduce an offset, use [`typed array`][mdn-typed-array] views.
@@ -74,49 +74,49 @@ var Complex128Array = require( '@stdlib/array/complex128' );
7474
var Complex128 = require( '@stdlib/complex/float64/ctor' );
7575

7676
// Initial array:
77-
var zx0 = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
77+
var x0 = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
7878

7979
// Define a scalar constant:
80-
var za = new Complex128( 2.0, 2.0 );
80+
var alpha = new Complex128( 2.0, 2.0 );
8181

8282
// Create an offset view:
83-
var zx1 = new Complex128Array( zx0.buffer, zx0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
83+
var x1 = new Complex128Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
8484

8585
// Scales every other value from `zx1` by `za`...
86-
zscal( 3, za, zx1, 1 );
87-
// zx0 => <Complex128Array>[ 1.0, 2.0, -2.0, 14.0, -2.0, 22.0, -2.0, 30.0 ]
86+
zscal( 3, alpha, x1, 1 );
87+
// x0 => <Complex128Array>[ 1.0, 2.0, -2.0, 14.0, -2.0, 22.0, -2.0, 30.0 ]
8888
```
8989

90-
#### zscal.ndarray( N, za, zx, strideX, offsetX )
90+
#### zscal.ndarray( N, alpha, x, strideX, offsetX )
9191

92-
Scales values from `zx` by `za` using alternative indexing semantics.
92+
Scales values from `x` by `alpha` using alternative indexing semantics.
9393

9494
```javascript
9595
var Complex128Array = require( '@stdlib/array/complex128' );
9696
var Complex128 = require( '@stdlib/complex/float64/ctor' );
9797

98-
var zx = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
99-
var za = new Complex128( 2.0, 2.0 );
98+
var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
99+
var alpha = new Complex128( 2.0, 2.0 );
100100

101-
zscal.ndarray( 3, za, zx, 1, 0 );
102-
// zx => <Complex128Array>[ -2.0, 6.0, -2.0, 14.0, -2.0, 22.0 ]
101+
zscal.ndarray( 3, alpha, x, 1, 0 );
102+
// x => <Complex128Array>[ -2.0, 6.0, -2.0, 14.0, -2.0, 22.0 ]
103103
```
104104

105105
The function has the following additional parameters:
106106

107-
- **offsetX**: starting index for `zx`.
107+
- **offsetX**: starting index for `x`.
108108

109109
While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying buffer, the offset parameter supports indexing semantics based on a starting index. For example, to scale every other value in the input strided array starting from the second element,
110110

111111
```javascript
112112
var Complex128Array = require( '@stdlib/array/complex128' );
113113
var Complex128 = require( '@stdlib/complex/float64/ctor' );
114114

115-
var zx = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
116-
var za = new Complex128( 2.0, 2.0 );
115+
var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
116+
var alpha = new Complex128( 2.0, 2.0 );
117117

118-
zscal.ndarray( 2, za, zx, 2, 1 );
119-
// zx => <Complex128Array>[ 1.0, 2.0, -2.0, 14.0, 5.0, 6.0, -2.0, 30.0 ]
118+
zscal.ndarray( 2, alpha, x, 2, 1 );
119+
// x => <Complex128Array>[ 1.0, 2.0, -2.0, 14.0, 5.0, 6.0, -2.0, 30.0 ]
120120
```
121121

122122
</section>
@@ -127,7 +127,7 @@ zscal.ndarray( 2, za, zx, 2, 1 );
127127

128128
## Notes
129129

130-
- If `N <= 0` or `strideX <= 0` , both functions return `zx` unchanged.
130+
- If `N <= 0` , both functions return `x` unchanged.
131131
- `zscal()` corresponds to the [BLAS][blas] level 1 function [`zscal`][zscal].
132132

133133
</section>
@@ -150,15 +150,15 @@ function rand() {
150150
return new Complex128( discreteUniform( 0, 10 ), discreteUniform( -5, 5 ) );
151151
}
152152

153-
var zx = filledarrayBy( 10, 'complex128', rand );
154-
console.log( zx.toString() );
153+
var x = filledarrayBy( 10, 'complex128', rand );
154+
console.log( x.toString() );
155155

156-
var za = new Complex128( 2.0, 2.0 );
157-
console.log( za.toString() );
156+
var alpha = new Complex128( 2.0, 2.0 );
157+
console.log( alpha.toString() );
158158

159-
// Scales elements from `zx` by `za`:
160-
zscal( zx.length, za, zx, 1 );
161-
console.log( zx.get( zx.length-1 ).toString() );
159+
// Scales elements from `x` by `alpha`:
160+
zscal( x.length, alpha, x, 1 );
161+
console.log( x.get( x.length-1 ).toString() );
162162
```
163163

164164
</section>
@@ -191,28 +191,53 @@ console.log( zx.get( zx.length-1 ).toString() );
191191
#include "stdlib/blas/base/zscal.h"
192192
```
193193

194-
#### c_zscal( N, za, \*ZX, strideX )
194+
#### c_zscal( N, alpha, \*X, strideX )
195195

196-
Scales values from `ZX` by `za`.
196+
Scales values from `X` by `alpha`.
197197

198198
```c
199199
#include "stdlib/complex/float64/ctor.h"
200200

201-
double zx[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
202-
const stdlib_complex128_t za = stdlib_complex128( 2.0, 2.0 );
201+
double x[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
202+
const stdlib_complex128_t alpha = stdlib_complex128( 2.0, 2.0 );
203203

204-
c_zscal( 4, za, (void *)zx, 1 );
204+
c_zscal( 4, alpha, (void *)x, 1 );
205205
```
206206
207207
The function accepts the following arguments:
208208
209209
- **N**: `[in] CBLAS_INT` number of indexed elements.
210-
- **za**: `[in] stdlib_complex128_t` scalar constant.
211-
- **ZX**: `[inout] void*` input array.
212-
- **strideX**: `[in] CBLAS_INT` index increment for `ZX`.
210+
- **alpha**: `[in] stdlib_complex128_t` scalar constant.
211+
- **X**: `[inout] void*` input array.
212+
- **strideX**: `[in] CBLAS_INT` index increment for `X`.
213213
214214
```c
215-
void c_zscal( const CBLAS_INT N, const stdlib_complex128_t za, void *ZX, const CBLAS_INT strideX );
215+
void c_zscal( const CBLAS_INT N, const stdlib_complex128_t alpha, void *X, const CBLAS_INT strideX );
216+
```
217+
218+
#### c_zscal_ndarray( N, alpha, \*X, strideX, offsetX )
219+
220+
Scales values from `X` by `alpha` using alternative indexing semantics.
221+
222+
```c
223+
#include "stdlib/complex/float64/ctor.h"
224+
225+
double x[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
226+
const stdlib_complex128_t alpha = stdlib_complex128( 2.0, 2.0 );
227+
228+
c_zscal_ndarray( 4, alpha, (void *)x, 1, 0 );
229+
```
230+
231+
The function accepts the following arguments:
232+
233+
- **N**: `[in] CBLAS_INT` number of indexed elements.
234+
- **alpha**: `[in] stdlib_complex128_t` scalar constant.
235+
- **X**: `[inout] void*` input array.
236+
- **strideX**: `[in] CBLAS_INT` index increment for `X`.
237+
- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
238+
239+
```c
240+
void c_zscal_ndarray( const CBLAS_INT N, const stdlib_complex128_t alpha, void *X, const CBLAS_INT strideX, const CBLAS_INT offsetX );
216241
```
217242

218243
</section>
@@ -240,10 +265,10 @@ void c_zscal( const CBLAS_INT N, const stdlib_complex128_t za, void *ZX, const C
240265

241266
int main( void ) {
242267
// Create a strided array of interleaved real and imaginary components:
243-
double zx[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
268+
double x[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
244269

245270
// Create a complex scalar:
246-
const stdlib_complex128_t ca = stdlib_complex128( 2.0, 2.0 );
271+
const stdlib_complex128_t alpha = stdlib_complex128( 2.0, 2.0 );
247272

248273
// Specify the number of elements:
249274
const int N = 4;
@@ -252,11 +277,19 @@ int main( void ) {
252277
const int strideX = 1;
253278

254279
// Scale the elements of the array:
255-
c_zscal( N, za, (void *)zx, strideX );
280+
c_zscal( N, alpha, (void *)x, strideX );
281+
282+
// Print the result:
283+
for ( int i = 0; i < N; i++ ) {
284+
printf( "x[ %i ] = %lf + %lfj\n", i, x[ i*2 ], x[ (i*2)+1 ] );
285+
}
286+
287+
// Scale the elements of the array using alternative indexing semantics:
288+
c_zscal_ndarray( N, alpha, (void *)x, -strideX, N-1 );
256289

257290
// Print the result:
258291
for ( int i = 0; i < N; i++ ) {
259-
printf( "zx[ %i ] = %f + %fj\n", i, zx[ i*2 ], zx[ (i*2)+1 ] );
292+
printf( "x[ %i ] = %lf + %lfj\n", i, x[ i*2 ], x[ (i*2)+1 ] );
260293
}
261294
}
262295
```

lib/node_modules/@stdlib/blas/base/zscal/benchmark/c/benchmark.length.c

+44-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @license Apache-2.0
33
*
4-
* Copyright (c) 2024 The Stdlib Authors.
4+
* Copyright (c) 2025 The Stdlib Authors.
55
*
66
* Licensed under the Apache License, Version 2.0 (the "License");
77
* you may not use this file except in compliance with the License.
@@ -95,7 +95,7 @@ static double rand_double( void ) {
9595
* @param len array length
9696
* @return elapsed time in seconds
9797
*/
98-
static double benchmark( int iterations, int len ) {
98+
static double benchmark1( int iterations, int len ) {
9999
stdlib_complex128_t za;
100100
double zx[ len*2 ];
101101
double elapsed;
@@ -122,6 +122,40 @@ static double benchmark( int iterations, int len ) {
122122
return elapsed;
123123
}
124124

125+
/**
126+
* Runs a benchmark.
127+
*
128+
* @param iterations number of iterations
129+
* @param len array length
130+
* @return elapsed time in seconds
131+
*/
132+
static double benchmark2( int iterations, int len ) {
133+
stdlib_complex128_t za;
134+
double zx[ len*2 ];
135+
double elapsed;
136+
double t;
137+
int i;
138+
139+
za = stdlib_complex128( 1.0, 0.0 );
140+
for ( i = 0; i < len*2; i+=2 ) {
141+
zx[ i ] = ( rand_double()*2.0 ) - 1.0;
142+
zx[ i+1 ] = ( rand_double()*2.0 ) - 1.0;
143+
}
144+
t = tic();
145+
for ( i = 0; i < iterations; i++ ) {
146+
c_zscal_ndarray( len, za, (void *)zx, 1, 0 );
147+
if ( zx[ 0 ] != zx[ 0 ] ) {
148+
printf( "should not return NaN\n" );
149+
break;
150+
}
151+
}
152+
elapsed = tic() - t;
153+
if ( zx[ 0 ] != zx[ 0 ] ) {
154+
printf( "should not return NaN\n" );
155+
}
156+
return elapsed;
157+
}
158+
125159
/**
126160
* Main execution sequence.
127161
*/
@@ -144,7 +178,14 @@ int main( void ) {
144178
for ( j = 0; j < REPEATS; j++ ) {
145179
count += 1;
146180
printf( "# c::%s:len=%d\n", NAME, len );
147-
elapsed = benchmark( iter, len );
181+
elapsed = benchmark1( iter, len );
182+
print_results( iter, elapsed );
183+
printf( "ok %d benchmark finished\n", count );
184+
}
185+
for ( j = 0; j < REPEATS; j++ ) {
186+
count += 1;
187+
printf( "# c::%s:ndarray:len=%d\n", NAME, len );
188+
elapsed = benchmark2( iter, len );
148189
print_results( iter, elapsed );
149190
printf( "ok %d benchmark finished\n", count );
150191
}

0 commit comments

Comments
 (0)