Skip to content

Commit 03fff24

Browse files
committed
Add BLAS level 1 routine sdot for ndarrays
1 parent 25fc0a1 commit 03fff24

File tree

12 files changed

+1683
-0
lines changed

12 files changed

+1683
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2020 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# sdot
22+
23+
> Calculate the dot product of two single-precision floating-point vectors.
24+
25+
<section class="intro">
26+
27+
The [dot product][dot-product] (or scalar product) is defined as
28+
29+
<!-- <equation class="equation" label="eq:dot_product" align="center" raw="\mathbf{x}\cdot\mathbf{y} = \sum_{i=0}^{N-1} x_i y_i = x_0 y_0 + x_1 y_1 + \ldots + x_{N-1} y_{N-1}" alt="Dot product definition."> -->
30+
31+
<div class="equation" align="center" data-raw-text="\mathbf{x}\cdot\mathbf{y} = \sum_{i=0}^{N-1} x_i y_i = x_0 y_0 + x_1 y_1 + \ldots + x_{N-1} y_{N-1}" data-equation="eq:dot_product">
32+
<img src="" alt="Dot product definition.">
33+
<br>
34+
</div>
35+
36+
<!-- </equation> -->
37+
38+
</section>
39+
40+
<!-- /.intro -->
41+
42+
<section class="usage">
43+
44+
## Usage
45+
46+
```javascript
47+
var sdot = require( '@stdlib/blas/sdot' );
48+
```
49+
50+
#### sdot( x, y\[, options] )
51+
52+
Calculates the dot product of vectors `x` and `y`.
53+
54+
```javascript
55+
var Float32Array = require( '@stdlib/array/float32' );
56+
var array = require( '@stdlib/ndarray/array' );
57+
58+
var x = array( new Float32Array( [ 4.0, 2.0, -3.0, 5.0, -1.0 ] ) );
59+
var y = array( new Float32Array( [ 2.0, 6.0, -1.0, -4.0, 8.0 ] ) );
60+
61+
var z = sdot( x, y );
62+
// returns -5.0
63+
```
64+
65+
The function has the following parameters:
66+
67+
- **x**: a 1-dimensional [`ndarray`][@stdlib/ndarray/array] or an array-like object. If provided an array-like object or [`ndarray`][@stdlib/ndarray/array] whose underlying data type is **not** `float32`, the value is cast to a 1-dimensional [`ndarray`][@stdlib/ndarray/array] whose data type is `float32`.
68+
- **y**: a 1-dimensional [`ndarray`][@stdlib/ndarray/array] or an array-like object. If provided an array-like object or [`ndarray`][@stdlib/ndarray/array] whose underlying data type is **not** `float32`, the value is cast to a 1-dimensional [`ndarray`][@stdlib/ndarray/array] whose data type is `float32`.
69+
70+
The function accepts the following `options`:
71+
72+
- `casting`: specifies the casting rule used to determine acceptable casts. The option may be one of the following values:
73+
74+
- `none`: only allow casting between identical types.
75+
- `equiv`: allow casting between identical and byte swapped types.
76+
- `safe`: only allow ["safe"][@stdlib/ndarray/safe-casts] casts.
77+
- `same-kind`: allow ["safe"][@stdlib/ndarray/safe-casts] casts and casts within the same kind (e.g., between signed integers or between floats).
78+
- `unsafe`: allow casting between all types (including between integers and floats).
79+
80+
Default: `'safe'`.
81+
82+
- `codegen`: `boolean` indicating whether to use code generation. Default: `true`.
83+
84+
Provided vectors may be either [`ndarrays`][@stdlib/ndarray/array] or array-like objects. By default, however, only array-like objects which can be [safely cast][@stdlib/ndarray/safe-casts] to `float32` are supported. In order to operate on numeric data stored in array-like objects which cannot be [safely cast][@stdlib/ndarray/safe-casts], one must explicitly set the `casting` option to `'unsafe'`. For example, because generic arrays can contain arbitrary data (including non-numeric types), thus allowing for potentially "unsafe" casts (e.g., strings representing integer values, such as "big integers", which cannot be accurately stored as single-precision floating-point numbers), one must explicitly set the `casting` option.
85+
86+
```javascript
87+
var x = [ 4.0, 2.0, -3.0, 5.0, -1.0 ];
88+
var y = [ 2.0, 6.0, -1.0, -4.0, 8.0 ];
89+
90+
var opts = {
91+
'casting': 'unsafe'
92+
};
93+
var z = sdot( x, y, opts );
94+
// returns -5.0
95+
```
96+
97+
If provided empty vectors, the function returns `0.0`.
98+
99+
```javascript
100+
var Float32Array = require( '@stdlib/array/float32' );
101+
var array = require( '@stdlib/ndarray/array' );
102+
103+
var x = array( new Float32Array() );
104+
var y = array( new Float32Array() );
105+
106+
var z = sdot( x, y );
107+
// returns 0.0
108+
```
109+
110+
</section>
111+
112+
<!-- /.usage -->
113+
114+
<section class="notes">
115+
116+
## Notes
117+
118+
- `sdot()` provides a higher-level interface to the [BLAS][blas] level 1 function [`sdot`][@stdlib/blas/base/sdot].
119+
- For best performance, provide 1-dimensional [`ndarrays`][@stdlib/ndarray/array] whose underlying data type is `float32`.
120+
- Options are only applicable when either `x` or `y` is not already an `ndarray` whose underlying data type is `float32`.
121+
- Code generation can boost performance, but may be problematic in browser contexts enforcing a strict [content security policy][mdn-csp] (CSP). If running in or targeting an environment with a CSP, set the `codegen` option to `false`.
122+
123+
</section>
124+
125+
<!-- /.notes -->
126+
127+
<section class="examples">
128+
129+
## Examples
130+
131+
<!-- eslint no-undef: "error" -->
132+
133+
```javascript
134+
var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
135+
var Float32Array = require( '@stdlib/array/float32' );
136+
var array = require( '@stdlib/ndarray/array' );
137+
var sdot = require( '@stdlib/blas/sdot' );
138+
139+
var x = array( new Float32Array( 10 ) );
140+
var y = array( new Float32Array( 10 ) );
141+
142+
var rand1 = discreteUniform.factory( 0, 100 );
143+
var rand2 = discreteUniform.factory( 0, 10 );
144+
145+
var i;
146+
for ( i = 0; i < x.length; i++ ) {
147+
x.set( i, rand1() );
148+
y.set( i, rand2() );
149+
}
150+
console.log( x.toString() );
151+
console.log( y.toString() );
152+
153+
var z = sdot( x, y );
154+
console.log( z );
155+
```
156+
157+
</section>
158+
159+
<!-- /.examples -->
160+
161+
<section class="links">
162+
163+
[dot-product]: https://en.wikipedia.org/wiki/Dot_product
164+
165+
[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
166+
167+
[blas]: http://www.netlib.org/blas
168+
169+
[@stdlib/blas/base/sdot]: https://github.com/stdlib-js/stdlib
170+
171+
[@stdlib/ndarray/array]: https://github.com/stdlib-js/stdlib
172+
173+
[@stdlib/ndarray/safe-casts]: https://github.com/stdlib-js/stdlib
174+
175+
</section>
176+
177+
<!-- /.links -->
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 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 bench = require( '@stdlib/bench' );
24+
var randu = require( '@stdlib/random/base/randu' );
25+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
26+
var pow = require( '@stdlib/math/base/special/pow' );
27+
var pkg = require( './../package.json' ).name;
28+
var sdot = require( './../lib/main.js' );
29+
30+
31+
// FUNCTIONS //
32+
33+
/**
34+
* Creates a benchmark function.
35+
*
36+
* @private
37+
* @param {PositiveInteger} len - array length
38+
* @returns {Function} benchmark function
39+
*/
40+
function createBenchmark( len ) {
41+
var opts;
42+
var x;
43+
var y;
44+
var i;
45+
46+
x = [];
47+
y = [];
48+
for ( i = 0; i < len; i++ ) {
49+
x.push( ( randu()*10.0 ) - 20.0 );
50+
y.push( ( randu()*10.0 ) - 20.0 );
51+
}
52+
opts = {
53+
'casting': 'unsafe'
54+
};
55+
return benchmark;
56+
57+
function benchmark( b ) {
58+
var d;
59+
var i;
60+
61+
b.tic();
62+
for ( i = 0; i < b.iterations; i++ ) {
63+
d = sdot( x, y, opts );
64+
if ( isnan( d ) ) {
65+
b.fail( 'should not return NaN' );
66+
}
67+
}
68+
b.toc();
69+
if ( isnan( d ) ) {
70+
b.fail( 'should not return NaN' );
71+
}
72+
b.pass( 'benchmark finished' );
73+
b.end();
74+
}
75+
}
76+
77+
78+
// MAIN //
79+
80+
/**
81+
* Main execution sequence.
82+
*
83+
* @private
84+
*/
85+
function main() {
86+
var len;
87+
var min;
88+
var max;
89+
var f;
90+
var i;
91+
92+
min = 1; // 10^min
93+
max = 6; // 10^max
94+
95+
for ( i = min; i <= max; i++ ) {
96+
len = pow( 10, i );
97+
f = createBenchmark( len );
98+
bench( pkg+'::with_casting:len='+len, f );
99+
}
100+
}
101+
102+
main();
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2020 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 bench = require( '@stdlib/bench' );
24+
var randu = require( '@stdlib/random/base/randu' );
25+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
26+
var pow = require( '@stdlib/math/base/special/pow' );
27+
var Float32Array = require( '@stdlib/array/float32' );
28+
var array = require( '@stdlib/ndarray/array' );
29+
var pkg = require( './../package.json' ).name;
30+
var sdot = require( './../lib/main.js' );
31+
32+
33+
// FUNCTIONS //
34+
35+
/**
36+
* Creates a benchmark function.
37+
*
38+
* @private
39+
* @param {PositiveInteger} len - array length
40+
* @returns {Function} benchmark function
41+
*/
42+
function createBenchmark( len ) {
43+
var x;
44+
var y;
45+
var i;
46+
47+
x = new Float32Array( len );
48+
y = new Float32Array( len );
49+
for ( i = 0; i < len; i++ ) {
50+
x[ i ] = ( randu()*10.0 ) - 20.0;
51+
y[ i ] = ( randu()*10.0 ) - 20.0;
52+
}
53+
x = array( x );
54+
y = array( y );
55+
56+
return benchmark;
57+
58+
function benchmark( b ) {
59+
var d;
60+
var i;
61+
62+
b.tic();
63+
for ( i = 0; i < b.iterations; i++ ) {
64+
d = sdot( x, y );
65+
if ( isnan( d ) ) {
66+
b.fail( 'should not return NaN' );
67+
}
68+
}
69+
b.toc();
70+
if ( isnan( d ) ) {
71+
b.fail( 'should not return NaN' );
72+
}
73+
b.pass( 'benchmark finished' );
74+
b.end();
75+
}
76+
}
77+
78+
79+
// MAIN //
80+
81+
/**
82+
* Main execution sequence.
83+
*
84+
* @private
85+
*/
86+
function main() {
87+
var len;
88+
var min;
89+
var max;
90+
var f;
91+
var i;
92+
93+
min = 1; // 10^min
94+
max = 6; // 10^max
95+
96+
for ( i = min; i <= max; i++ ) {
97+
len = pow( 10, i );
98+
f = createBenchmark( len );
99+
bench( pkg+':len='+len, f );
100+
}
101+
}
102+
103+
main();

0 commit comments

Comments
 (0)