Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c65133f
feat: create 2d version with its tests and benchmarks
LoayAhmed304 Mar 2, 2026
148d9d1
feat: add 0d implementation
LoayAhmed304 Mar 4, 2026
2a17361
feat: add 2d accessors implementation
LoayAhmed304 Mar 4, 2026
e3729ee
feat: add 2d blocked implementation
LoayAhmed304 Mar 4, 2026
cec872e
perf: use ternary loopOrder instead of unary
LoayAhmed304 Mar 4, 2026
1c48565
refactor: use proper indentation to follow editorconfig
LoayAhmed304 Mar 4, 2026
ccad894
refactor: disable max-len rule
LoayAhmed304 Mar 4, 2026
2df0faf
docs: fix the jsdoc to set the accessors
LoayAhmed304 Mar 4, 2026
5b71c61
fix: create getters and setters cache variables
LoayAhmed304 Mar 4, 2026
c1ddf9b
feat: add 2d blocked accessors
LoayAhmed304 Mar 4, 2026
b672f66
feat: add 1d and its accessors version
LoayAhmed304 Mar 4, 2026
f470119
feat: add 3d implementations
LoayAhmed304 Mar 5, 2026
fefa9ab
feat: add 4d implementations
LoayAhmed304 Mar 5, 2026
1fba261
feat: add 5d implementations
LoayAhmed304 Mar 5, 2026
b89c478
feat: add 6d implementations
LoayAhmed304 Mar 5, 2026
c93b341
feat: add 7d implementations
LoayAhmed304 Mar 5, 2026
4b2706e
feat: add 8d implementations
LoayAhmed304 Mar 6, 2026
5d33b18
feat: add 9d implementations
LoayAhmed304 Mar 6, 2026
d4450cf
feat: add 10d implementations
LoayAhmed304 Mar 6, 2026
8af00b1
feat: add nd implementations
LoayAhmed304 Mar 6, 2026
afcc970
feat(WIP): create main.js and index.js
LoayAhmed304 Mar 6, 2026
372165a
test: add tests
LoayAhmed304 Mar 7, 2026
f522872
docs: add examples, docs and README.md
LoayAhmed304 Mar 7, 2026
8fb5a0b
test: add up to 3d tests and benchmarks
LoayAhmed304 Mar 16, 2026
e5a8f91
test: add up to 3d tests and benchmarks
LoayAhmed304 Mar 16, 2026
559c59c
docs: update ndarray/base README.md
LoayAhmed304 Mar 16, 2026
9ef3b15
Merge branch 'feat/base-ndarray-where' of https://github.com/LoayAhme…
LoayAhmed304 Mar 16, 2026
1205cdc
refactor: remove lint warnings
LoayAhmed304 Mar 16, 2026
3735e43
refactor: apply the requested changes
LoayAhmed304 Mar 17, 2026
7230913
refactor: refactor main.js logic and edge cases handling
LoayAhmed304 Mar 17, 2026
0c3a27c
chore: apply requested changes
LoayAhmed304 Mar 24, 2026
95e9b66
Update main.js
LoayAhmed304 Mar 25, 2026
fb2a747
chore: apply requested changes
LoayAhmed304 Mar 25, 2026
56b0665
fix: remove always condition array reinterpretation
LoayAhmed304 Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 221 additions & 0 deletions lib/node_modules/@stdlib/ndarray/base/where/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
<!--

@license Apache-2.0

Copyright (c) 2026 The Stdlib Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->

# Where

> Apply a condition to elements in two input ndarrays and assign results to elements in an output ndarray.

<section class="intro">

</section>

<!-- /.intro -->

<section class="usage">

## Usage

```javascript
var where = require( '@stdlib/ndarray/base/where' );
```

#### where( arrays )

Applies a condition to elements in two input ndarrays and assigns results to elements in an output ndarray.

<!-- eslint-disable max-len -->

```javascript
var Float64Array = require( '@stdlib/array/float64' );
var Uint8Array = require( '@stdlib/array/uint8' );

// Create data buffers:
var cbuf = new Uint8Array( [ 1, 0, 0, 1, 0, 1 ] );
var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
var ybuf = new Float64Array( [ -1.0, -2.0, -3.0, -4.0, -5.0, -6.0 ] );
var obuf = new Float64Array( 6 );

// Define the shape of the input and output arrays:
var shape = [ 3, 1, 2 ];

// Define the array strides:
var sc = [ 2, 2, 1 ];
var sx = [ 2, 2, 1 ];
var sy = [ 2, 2, 1 ];
var so = [ 2, 2, 1 ];

// Define the index offsets:
var oc = 0;
var ox = 0;
var oy = 0;
var oo = 0;

// Create the input and output ndarrays:
var condition = {
'dtype': 'uint8',
'data': cbuf,
'shape': shape,
'strides': sc,
'offset': oc,
'order': 'row-major'
};
var x = {
'dtype': 'float64',
'data': xbuf,
'shape': shape,
'strides': sx,
'offset': ox,
'order': 'row-major'
};
var y = {
'dtype': 'float64',
'data': ybuf,
'shape': shape,
'strides': sy,
'offset': oy,
'order': 'row-major'
};
var out = {
'dtype': 'float64',
'data': obuf,
'shape': shape,
'strides': so,
'offset': oo,
'order': 'row-major'
};

// Apply the condition:
where( [ condition, x, y, out ] );
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LoayAhmed304 It's better to use contiguous arrays in this example. Otherwise, the reader has to mentally compute which elements are accessed.

Also, why does the condition have to be the first ndarray? why does have to be named condition?

You need to be consistent with stdlib conventions. You can use ndarray/base/ternary as a reference. This likely applies to other files as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^^ Condition is the first array per the Array API specification.

Copy link
Copy Markdown
Member

@headlessNode headlessNode Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kgryte IMO this approach doesn't line up with either stdlib or the Array API standard. The Array API version of where takes three separate arguments: where(condition, x1, x2) whereas ndarray/base/* functions are like so ternary( [ x, y, z, w ] ).

I'd say keep ndarray/base/where something like where( [ x, y, c, o ] ) (names can vary), and have the user-facing ndarray/where follow the Array API Standard where( condition, x1, x2 ). That way, we stay consistent with both.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@headlessNode I guess I am not following why [ condition, x, y, out ] is somehow inconsistent. condition isn't an auxiliary ndarray, such as sort order, etc. You could simply rename condition => x, x => y, and y => z, and you'd get your desired naming scheme. I suppose I am not seeing why the condition array shouldn't be the first ndarray. And the reason for it being named "condition" is that is what it behaviorally does.

In general, it is fine if an API semantically has different argument names than the underlying kernel package. ternary could have just as well called them x1, x2, x3, x4. So I am not quite understanding the consistency argument here and where the confusion would arise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kgryte condition not being auxiliary didn't cross my mind. And aside from the Array Api Standard the first array being condition makes more sense if we think about it like so: "where condition, choose x else y".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@headlessNode Regarding the contiguous arrays, I used such example(s) referencing to assign example, I can update this and other examples if needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use a simpler example here but it's not a hard requirement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. On it.


console.log( out.data );
// => <Float64Array>[ 1.0, -2.0, -3.0, 4.0, -5.0, 6.0 ]
```

The function accepts the following arguments:

- **arrays**: array-like object containing three input ndarrays and one output ndarray.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is okay since in the main description 'a condition' and 'two input ndarrays' is used.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you decide to change, it would apply to repl and index.d.ts file as well.


Each provided ndarray should be an object with the following properties:

- **dtype**: data type.
- **data**: data buffer.
- **shape**: dimensions.
- **strides**: stride lengths.
- **offset**: index offset.
- **order**: specifies whether an ndarray is row-major (C-style) or column major (Fortran-style).

</section>

<!-- /.usage -->

<section class="notes">

## Notes

- `condition` ndarray must be a `boolean` or `uint8` ndarray.
- `condition`, `x`, `y`, and `out` ndarrays must have the same shape.
- For very high-dimensional ndarrays which are non-contiguous, one should consider copying the underlying data to contiguous memory before conditionally assigning elements in order to achieve better performance.

</section>

<!-- /.notes -->

<section class="examples">

## Examples

<!-- eslint no-undef: "error" -->

```javascript
var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ).factory;
var bernoulli = require( '@stdlib/random/base/bernoulli' ).factory;
var filledarray = require( '@stdlib/array/filled' );
var filledarrayBy = require( '@stdlib/array/filled-by' );
var shape2strides = require( '@stdlib/ndarray/base/shape2strides' );
var ndarray2array = require( '@stdlib/ndarray/base/to-array' );
var where = require( '@stdlib/ndarray/base/where' );

var N = 10;
var shape = [ 5, 2 ];
var condition = {
'dtype': 'uint8',
'data': filledarrayBy( N, 'uint8', bernoulli( 0.5 ) ),
'shape': shape,
'strides': [ 2, 1 ],
'offset': 0,
'order': 'row-major'
};
console.log( ndarray2array( condition.data, condition.shape, condition.strides, condition.offset, condition.order ) ); // eslint-disable-line max-len

var x = {
'dtype': 'generic',
'data': filledarrayBy( N, 'generic', discreteUniform( 0, 100 ) ),
'shape': shape,
'strides': [ 2, 1 ],
'offset': 0,
'order': 'row-major'
};
console.log( ndarray2array( x.data, x.shape, x.strides, x.offset, x.order ) );

var y = {
'dtype': 'generic',
'data': filledarrayBy( N, 'generic', discreteUniform( -100, 0 ) ),
'shape': shape,
'strides': [ 2, 1 ],
'offset': 0,
'order': 'row-major'
};
console.log( ndarray2array( y.data, y.shape, y.strides, y.offset, y.order ) );

var out = {
'dtype': 'generic',
'data': filledarray( 0, N, 'generic' ),
'shape': shape.slice(),
'strides': shape2strides( shape, 'column-major' ),
'offset': 0,
'order': 'column-major'
};

where( [ condition, x, y, out ] );
console.log( ndarray2array( out.data, out.shape, out.strides, out.offset, out.order ) ); // eslint-disable-line max-len

```

</section>

<!-- /.examples -->

<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->

<section class="related">

</section>

<!-- /.related -->

<section class="links">

<!-- <related-links> -->

<!-- </related-links> -->

</section>

<!-- /.links -->
Loading
Loading