Skip to content

Commit eb60bb4

Browse files
headlessNodekgryte
andauthored
feat: add blas/ext/base/dcartesian-product
PR-URL: #10799 Co-authored-by: Athan Reines <kgryte@gmail.com> Reviewed-by: Athan Reines <kgryte@gmail.com> Signed-off-by: Athan Reines <kgryte@gmail.com> Closes: stdlib-js/metr-issue-tracker#173
1 parent d69f7f9 commit eb60bb4

33 files changed

Lines changed: 5049 additions & 0 deletions
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2026 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+
# dcartesianProduct
22+
23+
> Compute the Cartesian product for two double-precision floating-point strided arrays.
24+
25+
<section class="usage">
26+
27+
## Usage
28+
29+
```javascript
30+
var dcartesianProduct = require( '@stdlib/blas/ext/base/dcartesian-product' );
31+
```
32+
33+
#### dcartesianProduct( order, M, N, x, strideX, y, strideY, out, LDO )
34+
35+
Computes the Cartesian product for two double-precision floating-point strided arrays.
36+
37+
```javascript
38+
var Float64Array = require( '@stdlib/array/float64' );
39+
40+
var x = new Float64Array( [ 1.0, 2.0 ] );
41+
var y = new Float64Array( [ 3.0, 4.0 ] );
42+
var out = new Float64Array( 8 );
43+
44+
// Compute the Cartesian product:
45+
dcartesianProduct( 'row-major', x.length, y.length, x, 1, y, 1, out, 2 );
46+
// out => <Float64Array>[ 1.0, 3.0, 1.0, 4.0, 2.0, 3.0, 2.0, 4.0 ]
47+
```
48+
49+
The function has the following parameters:
50+
51+
- **order**: storage layout.
52+
- **M**: number of indexed elements in `x`.
53+
- **N**: number of indexed elements in `y`.
54+
- **x**: first input [`Float64Array`][@stdlib/array/float64].
55+
- **strideX**: stride length for `x`.
56+
- **y**: second input [`Float64Array`][@stdlib/array/float64].
57+
- **strideY**: stride length for `y`.
58+
- **out**: output [`Float64Array`][@stdlib/array/float64].
59+
- **LDO**: stride length between successive contiguous vectors of the matrix `out` (a.k.a., leading dimension of `out`).
60+
61+
The `M`, `N` and stride parameters determine which elements in the strided arrays are accessed at runtime. For example, to compute the Cartesian product of every other element:
62+
63+
```javascript
64+
var Float64Array = require( '@stdlib/array/float64' );
65+
66+
var x = new Float64Array( [ 1.0, 0.0, 2.0, 0.0 ] );
67+
var y = new Float64Array( [ 3.0, 0.0, 4.0, 0.0 ] );
68+
var out = new Float64Array( 8 );
69+
70+
// Compute the Cartesian product:
71+
dcartesianProduct( 'row-major', 2, 2, x, 2, y, 2, out, 2 );
72+
// out => <Float64Array>[ 1.0, 3.0, 1.0, 4.0, 2.0, 3.0, 2.0, 4.0 ]
73+
```
74+
75+
Note that indexing is relative to the first index. To introduce an offset, use [`typed array`][mdn-typed-array] views.
76+
77+
```javascript
78+
var Float64Array = require( '@stdlib/array/float64' );
79+
80+
// Initial arrays...
81+
var x0 = new Float64Array( [ 0.0, 1.0, 2.0 ] );
82+
var y0 = new Float64Array( [ 0.0, 3.0, 4.0 ] );
83+
84+
// Create offset views...
85+
var x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
86+
var y1 = new Float64Array( y0.buffer, y0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
87+
88+
var out = new Float64Array( 8 );
89+
90+
// Compute the Cartesian product:
91+
dcartesianProduct( 'row-major', 2, 2, x1, 1, y1, 1, out, 2 );
92+
// out => <Float64Array>[ 1.0, 3.0, 1.0, 4.0, 2.0, 3.0, 2.0, 4.0 ]
93+
```
94+
95+
<!--lint disable maximum-heading-length-->
96+
97+
#### dcartesianProduct.ndarray( M, N, x, strideX, offsetX, y, strideY, offsetY, out, strideOut1, strideOut2, offsetOut )
98+
99+
<!--lint enable maximum-heading-length-->
100+
101+
Computes the Cartesian product for two double-precision floating-point strided arrays using alternative indexing semantics.
102+
103+
```javascript
104+
var Float64Array = require( '@stdlib/array/float64' );
105+
106+
var x = new Float64Array( [ 1.0, 2.0 ] );
107+
var y = new Float64Array( [ 3.0, 4.0 ] );
108+
var out = new Float64Array( 8 );
109+
110+
// Compute the Cartesian product:
111+
dcartesianProduct.ndarray( x.length, y.length, x, 1, 0, y, 1, 0, out, 2, 1, 0 );
112+
// out => <Float64Array>[ 1.0, 3.0, 1.0, 4.0, 2.0, 3.0, 2.0, 4.0 ]
113+
```
114+
115+
The function has the following additional parameters:
116+
117+
- **offsetX**: starting index for `x`.
118+
- **offsetY**: starting index for `y`.
119+
- **strideOut1**: stride length for the first dimension of `out`.
120+
- **strideOut2**: stride length for the second dimension of `out`.
121+
- **offsetOut**: starting index for `out`.
122+
123+
While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying buffer, the offset parameters support indexing semantics based on starting indices. For example, to access only the last two elements:
124+
125+
```javascript
126+
var Float64Array = require( '@stdlib/array/float64' );
127+
128+
var x = new Float64Array( [ 0.0, 0.0, 1.0, 2.0 ] );
129+
var y = new Float64Array( [ 0.0, 0.0, 3.0, 4.0 ] );
130+
var out = new Float64Array( 8 );
131+
132+
// Compute the Cartesian product:
133+
dcartesianProduct.ndarray( 2, 2, x, 1, 2, y, 1, 2, out, 2, 1, 0 );
134+
// out => <Float64Array>[ 1.0, 3.0, 1.0, 4.0, 2.0, 3.0, 2.0, 4.0 ]
135+
```
136+
137+
</section>
138+
139+
<!-- /.usage -->
140+
141+
<section class="notes">
142+
143+
## Notes
144+
145+
- If `M <= 0` or `N <= 0`, both functions return `out` unchanged.
146+
- Pairs are stored as rows in the output matrix, where the first column contains the first element of each pair and the second column contains the second element.
147+
- For input arrays `x` of length `M` and `y` of length `N`, the output array must contain at least `M * N * 2` indexed elements.
148+
- For row-major order, the `LDO` parameter must be greater than or equal to `2`. For column-major order, the `LDO` parameter must be greater than or equal to `max(1,M*N)`.
149+
150+
</section>
151+
152+
<!-- /.notes -->
153+
154+
<section class="examples">
155+
156+
## Examples
157+
158+
<!-- eslint no-undef: "error" -->
159+
160+
```javascript
161+
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
162+
var Float64Array = require( '@stdlib/array/float64' );
163+
var dcartesianProduct = require( '@stdlib/blas/ext/base/dcartesian-product' );
164+
165+
var M = 3;
166+
var N = 2;
167+
var x = discreteUniform( M, 1, 10, {
168+
'dtype': 'float64'
169+
});
170+
console.log( x );
171+
172+
var y = discreteUniform( N, 1, 10, {
173+
'dtype': 'float64'
174+
});
175+
console.log( y );
176+
177+
var out = new Float64Array( M * N * 2 );
178+
179+
// Compute the Cartesian product:
180+
dcartesianProduct( 'row-major', M, N, x, 1, y, 1, out, 2 );
181+
console.log( out );
182+
```
183+
184+
</section>
185+
186+
<!-- /.examples -->
187+
188+
<!-- C interface documentation. -->
189+
190+
* * *
191+
192+
<section class="c">
193+
194+
## C APIs
195+
196+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
197+
198+
<section class="intro">
199+
200+
</section>
201+
202+
<!-- /.intro -->
203+
204+
<!-- C usage documentation. -->
205+
206+
<section class="usage">
207+
208+
### Usage
209+
210+
```c
211+
#include "stdlib/blas/ext/base/dcartesianproduct.h"
212+
```
213+
214+
<!--lint disable maximum-heading-length-->
215+
216+
#### stdlib_strided_dcartesian_product( order, M, N, \*X, strideX, \*Y, strideY, \*Out, LDO )
217+
218+
<!--lint enable maximum-heading-length-->
219+
220+
Computes the Cartesian product for two double-precision floating-point strided arrays.
221+
222+
```c
223+
#include "stdlib/blas/base/shared.h"
224+
225+
const double x[] = { 1.0, 2.0 };
226+
const double y[] = { 3.0, 4.0 };
227+
double out[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
228+
229+
stdlib_strided_dcartesian_product( CblasRowMajor, 2, 2, x, 1, y, 1, out, 2 );
230+
```
231+
232+
The function accepts the following arguments:
233+
234+
- **order**: `[in] CBLAS_LAYOUT` storage layout.
235+
- **M**: `[in] CBLAS_INT` number of indexed elements in `X`.
236+
- **N**: `[in] CBLAS_INT` number of indexed elements in `Y`.
237+
- **X**: `[in] double*` first input array.
238+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
239+
- **Y**: `[in] double*` second input array.
240+
- **strideY**: `[in] CBLAS_INT` stride length for `Y`.
241+
- **Out**: `[out] double*` output array.
242+
- **LDO**: `[in] CBLAS_INT` stride length between successive contiguous vectors of the matrix `Out` (a.k.a., leading dimension of `Out`). For row-major order, must be greater than or equal to `2`. For column-major order, must be greater than or equal to `max(1,M*N)`.
243+
244+
```c
245+
void stdlib_strided_dcartesian_product( const CBLAS_LAYOUT order, const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const double *Y, const CBLAS_INT strideY, double *Out, const CBLAS_INT LDO );
246+
```
247+
248+
<!--lint disable maximum-heading-length-->
249+
250+
#### stdlib_strided_dcartesian_product_ndarray( M, N, \*X, strideX, offsetX, \*Y, strideY, offsetY, \*Out, strideOut1, strideOut2, offsetOut )
251+
252+
<!--lint enable maximum-heading-length-->
253+
254+
Computes the Cartesian product for two double-precision floating-point strided arrays using alternative indexing semantics.
255+
256+
```c
257+
const double x[] = { 1.0, 2.0 };
258+
const double y[] = { 3.0, 4.0 };
259+
double out[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
260+
261+
stdlib_strided_dcartesian_product_ndarray( 2, 2, x, 1, 0, y, 1, 0, out, 2, 1, 0 );
262+
```
263+
264+
The function accepts the following arguments:
265+
266+
- **M**: `[in] CBLAS_INT` number of indexed elements in `X`.
267+
- **N**: `[in] CBLAS_INT` number of indexed elements in `Y`.
268+
- **X**: `[in] double*` first input array.
269+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
270+
- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
271+
- **Y**: `[in] double*` second input array.
272+
- **strideY**: `[in] CBLAS_INT` stride length for `Y`.
273+
- **offsetY**: `[in] CBLAS_INT` starting index for `Y`.
274+
- **Out**: `[out] double*` output array.
275+
- **strideOut1**: `[in] CBLAS_INT` stride length for the first dimension of `Out`.
276+
- **strideOut2**: `[in] CBLAS_INT` stride length for the second dimension of `Out`.
277+
- **offsetOut**: `[in] CBLAS_INT` starting index for `Out`.
278+
279+
```c
280+
void stdlib_strided_dcartesian_product_ndarray( const CBLAS_INT M, const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, const double *Y, const CBLAS_INT strideY, const CBLAS_INT offsetY, double *Out, const CBLAS_INT strideOut1, const CBLAS_INT strideOut2, const CBLAS_INT offsetOut );
281+
```
282+
283+
</section>
284+
285+
<!-- /.usage -->
286+
287+
<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
288+
289+
<section class="notes">
290+
291+
</section>
292+
293+
<!-- /.notes -->
294+
295+
<!-- C API usage examples. -->
296+
297+
<section class="examples">
298+
299+
### Examples
300+
301+
```c
302+
#include "stdlib/blas/ext/base/dcartesianproduct.h"
303+
#include "stdlib/blas/base/shared.h"
304+
#include <stdio.h>
305+
306+
int main( void ) {
307+
// Create strided input arrays:
308+
const double X[] = { 1.0, 2.0, 3.0, 4.0 };
309+
const double Y[] = { 5.0, 6.0, 7.0, 8.0 };
310+
311+
// Specify the number of indexed elements:
312+
const int M = 4;
313+
const int N = 4;
314+
315+
// Create an output array (M*N pairs, each pair has 2 elements):
316+
double out[ 32 ];
317+
318+
// Specify strides:
319+
const int strideX = 1;
320+
const int strideY = 1;
321+
const int LDO = 2;
322+
323+
// Compute the Cartesian product:
324+
stdlib_strided_dcartesian_product( CblasRowMajor, M, N, X, strideX, Y, strideY, out, LDO );
325+
326+
// Print the result:
327+
for ( int i = 0; i < M*N; i++ ) {
328+
printf( "out[ %i ] = ( %lf, %lf )\n", i, out[ i*2 ], out[ (i*2)+1 ] );
329+
}
330+
}
331+
```
332+
333+
</section>
334+
335+
<!-- /.examples -->
336+
337+
</section>
338+
339+
<!-- /.c -->
340+
341+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
342+
343+
<section class="related">
344+
345+
</section>
346+
347+
<!-- /.related -->
348+
349+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
350+
351+
<section class="links">
352+
353+
[@stdlib/array/float64]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/float64
354+
355+
[mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
356+
357+
</section>
358+
359+
<!-- /.links -->

0 commit comments

Comments
 (0)