Skip to content

Commit fb1ca76

Browse files
committed
feat: add ndarray/to-fancy
1 parent 14427c7 commit fb1ca76

39 files changed

+6479
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2024 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+
# ndarray2fancy
22+
23+
> Convert an ndarray to an object supporting fancy indexing.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
A fancy ndarray is an [`ndarray`][@stdlib/ndarray/ctor] which supports slicing via indexing expressions.
30+
31+
```javascript
32+
var ndarray2array = require( '@stdlib/ndarray/to-array' );
33+
var ndarray = require( '@stdlib/ndarray/ctor' );
34+
35+
// Create a plain ndarray:
36+
var buffer = [ 1, 2, 3, 4, 5, 6 ];
37+
var x = new ndarray( 'generic', buffer, [ 6 ], [ 1 ], 0, 'row-major' );
38+
// returns <ndarray>
39+
40+
// Convert to a fancy ndarray:
41+
var y = ndarray2fancy( x );
42+
43+
// Select the first 3 elements:
44+
var z = y[ ':3' ];
45+
// returns <ndarray>
46+
47+
var arr = ndarray2array( z );
48+
// returns [ 1, 2, 3 ]
49+
50+
// Select every other element, starting with the second element:
51+
z = y[ '1::2' ];
52+
// returns <ndarray>
53+
54+
arr = ndarray2array( z );
55+
// returns [ 2, 4, 6 ]
56+
57+
// Reverse the array, starting with last element and skipping every other element:
58+
z = y[ '::-2' ];
59+
// returns <ndarray>
60+
61+
arr = ndarray2array( z );
62+
// returns [ 6, 4, 2 ]
63+
```
64+
65+
</section>
66+
67+
<!-- /.intro -->
68+
69+
<!-- Package usage documentation. -->
70+
71+
<section class="usage">
72+
73+
## Usage
74+
75+
```javascript
76+
var ndarray2fancy = require( '@stdlib/ndarray/to-fancy' );
77+
```
78+
79+
#### ndarray2fancy( x\[, options] )
80+
81+
Converts an [ndarray][@stdlib/ndarray/ctor] to an object supporting fancy indexing.
82+
83+
```javascript
84+
console.log( 'TODO' );
85+
```
86+
87+
The function supports the following options:
88+
89+
- **cache**: cache for resolving ndarray index objects. Must have a `get` method which accepts a single argument: a string identifier associated with an ndarray index.
90+
91+
If an ndarray index associated with a provided identifier exists, the `get` method should return an object having the following properties:
92+
93+
- **data**: the underlying index ndarray.
94+
- **type**: the index type. Must be either `'mask'`, `'bool'`, or `'int'`.
95+
- **dtype**: the [data type][@stdlib/ndarray/dtypes] of the underlying ndarray.
96+
97+
If an ndarray index is not associated with a provided identifier, the `get` method should return `null`.
98+
99+
Default: [`ndindex`][@stdlib/ndarray/index].
100+
101+
- **strict**: boolean indicating whether to enforce strict bounds checking. Default: `false`.
102+
103+
By default, the function returns a fancy ndarray which does **not** enforce strict bounds checking. For example,
104+
105+
```javascript
106+
console.log( 'TODO' );
107+
```
108+
109+
To enforce strict bounds checking, set the `strict` option to `true`.
110+
111+
<!-- run throws: true -->
112+
113+
```javascript
114+
console.log( 'TODO' );
115+
```
116+
117+
#### ndarray2fancy.factory( \[options] )
118+
119+
Returns a function for converting an [ndarray][@stdlib/ndarray/ctor] to an object supporting fancy indexing.
120+
121+
```javascript
122+
var fcn = ndarray2fancy.factory();
123+
124+
console.log( 'TODO' );
125+
```
126+
127+
The function supports the following options:
128+
129+
- **cache**: default cache for resolving ndarray index objects. Must have a `get` method which accepts a single argument: a string identifier associated with an ndarray index.
130+
131+
If an ndarray index associated with a provided identifier exists, the `get` method should return an object having the following properties:
132+
133+
- **data**: the underlying index ndarray.
134+
- **type**: the index type. Must be either `'mask'`, `'bool'`, or `'int'`.
135+
- **dtype**: the [data type][@stdlib/ndarray/dtypes] of the underlying ndarray.
136+
137+
If an ndarray index is not associated with a provided identifier, the `get` method should return `null`.
138+
139+
Default: [`ndindex`][@stdlib/ndarray/index].
140+
141+
- **strict**: boolean indicating whether to enforce strict bounds checking by default. Default: `false`.
142+
143+
By default, the function returns a function which, by default, does **not** enforce strict bounds checking. For example,
144+
145+
```javascript
146+
var fcn = ndarray2fancy.factory();
147+
148+
console.log( 'TODO' );
149+
```
150+
151+
To enforce strict bounds checking by default, set the `strict` option to `true`.
152+
153+
<!-- run throws: true -->
154+
155+
```javascript
156+
var fcn = ndarray2fancy.factory({
157+
'strict': true
158+
});
159+
160+
console.log( 'TODO' );
161+
```
162+
163+
The returned function supports the same options as above. When the returned function is provided option values, those values override the factory method defaults.
164+
165+
#### ndarray2fancy.idx( x\[, options] )
166+
167+
Wraps a provided ndarray as an ndarray index object.
168+
169+
```javascript
170+
console.log( 'TODO' );
171+
```
172+
173+
For documentation and usage, see [`ndindex`][@stdlib/ndarray/index].
174+
175+
</section>
176+
177+
<!-- /.usage -->
178+
179+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
180+
181+
<section class="notes">
182+
183+
* * *
184+
185+
## Notes
186+
187+
- A fancy ndarray shares the **same** data as the provided input [ndarray][@stdlib/ndarray/ctor]. Hence, any mutations to the returned ndarray will affect the underlying input ndarray and vice versa.
188+
- For operations returning a new ndarray (e.g., when slicing or invoking an instance method), a fancy ndarray returns a new fancy ndarray having the same configuration as specified by `options`.
189+
- A fancy ndarray supports indexing using positive and negative integers (both numeric literals and strings), [`Slice`][@stdlib/slice/ctor] and [`MultiSlice`][@stdlib/slice/multi] instances, [subsequence expressions][@stdlib/slice/seq2multislice], and [index arrays][@stdlib/ndarray/index] (boolean, mask, and integer).
190+
- A fancy ndarray supports all properties and methods of the input ndarray, and, thus, a fancy ndarray can be consumed by any API which supports ndarray-like objects.
191+
- Indexing expressions provide a convenient and powerful means for creating and operating on ndarray views; however, their use does entail a performance cost. Indexing expressions are best suited for interactive use (e.g., in the [REPL][@stdlib/repl]) and scripting. For performance critical applications, prefer equivalent functional APIs supporting ndarray-like objects.
192+
- In older JavaScript environments which do **not** support [`Proxy`][@stdlib/proxy/ctor] objects, the use of indexing expressions is **not** supported.
193+
194+
### Bounds Checking
195+
196+
// TODO: see array/to-fancy
197+
198+
### Broadcasting
199+
200+
// TODO: see array/to-fancy
201+
202+
### Casting
203+
204+
// TODO: see array/to-fancy
205+
206+
</section>
207+
208+
<!-- /.notes -->
209+
210+
<!-- Package usage examples. -->
211+
212+
<section class="examples">
213+
214+
* * *
215+
216+
## Examples
217+
218+
<!-- eslint no-undef: "error" -->
219+
220+
<!-- eslint-disable new-cap, array-element-newline, comma-spacing -->
221+
222+
```javascript
223+
var S = require( '@stdlib/slice/ctor' );
224+
var E = require( '@stdlib/slice/multi' );
225+
var toArray = require( '@stdlib/ndarray/to-array' );
226+
var ndarray = require( '@stdlib/ndarray/ctor' );
227+
var ndarray2fancy = require( '@stdlib/ndarray/to-fancy' );
228+
229+
var buffer = [
230+
1, 2,
231+
3, 4, // 0
232+
5, 6, // 1
233+
7, 8, // 2
234+
9, 10
235+
];
236+
var shape = [ 3, 2 ];
237+
var strides = [ 2, 1 ];
238+
var offset = 2;
239+
240+
// Create a normal ndarray:
241+
var x = new ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
242+
// returns <ndarray>
243+
244+
// Convert to a fancy ndarray:
245+
var y = ndarray2fancy( x );
246+
247+
// Access an ndarray property:
248+
var ndims = y.ndims;
249+
// returns 2
250+
251+
// Retrieve an ndarray element:
252+
var v = y.get( 2, 1 );
253+
// returns 8
254+
255+
// Set an ndarray element:
256+
y.set( 2, 1, 20 );
257+
v = y.get( 2, 1 );
258+
// returns 20
259+
260+
// Create an alias for `undefined` for more concise slicing expressions:
261+
var _ = void 0;
262+
263+
// Create a multi-dimensional slice:
264+
var s = E( S(0,_,2), _ );
265+
// returns <MultiSlice>
266+
267+
// Use the slice to create a view on the original ndarray:
268+
var y1 = y[ s ];
269+
console.log( toArray( y1 ) );
270+
// => [ [ 3, 4 ], [ 7, 20 ] ]
271+
272+
// Use alternative syntax:
273+
var y2 = y[ [ S(0,_,2), _ ] ];
274+
console.log( toArray( y2 ) );
275+
// => [ [ 3, 4 ], [ 7, 20 ] ]
276+
277+
// Use alternative syntax:
278+
var y3 = y[ '0::2,:' ];
279+
console.log( toArray( y3 ) );
280+
// => [ [ 3, 4 ], [ 7, 20 ] ]
281+
282+
// Flip dimensions:
283+
var y4 = y[ [ S(_,_,-2), S(_,_,-1) ] ];
284+
console.log( toArray( y4 ) );
285+
// => [ [ 20, 7 ], [ 4, 3 ] ]
286+
```
287+
288+
</section>
289+
290+
<!-- /.examples -->
291+
292+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
293+
294+
<section class="references">
295+
296+
</section>
297+
298+
<!-- /.references -->
299+
300+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
301+
302+
<section class="related">
303+
304+
</section>
305+
306+
<!-- /.related -->
307+
308+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
309+
310+
<section class="links">
311+
312+
[@stdlib/ndarray/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/ctor
313+
314+
[@stdlib/ndarray/dtypes]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/dtypes
315+
316+
[@stdlib/ndarray/index]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/index
317+
318+
[@stdlib/repl]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/repl
319+
320+
[@stdlib/proxy/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/proxy/ctor
321+
322+
[@stdlib/slice/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/slice/ctor
323+
324+
[@stdlib/slice/multi]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/slice/multi
325+
326+
[@stdlib/slice/seq2multislice]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/slice/seq2multislice
327+
328+
</section>
329+
330+
<!-- /.links -->

0 commit comments

Comments
 (0)