Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
82 changes: 82 additions & 0 deletions .ralph/state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Ralph Loop State

## Issue
**Reference**: stdlib-js/todo#2772
**Title**: Review `@stdlib/ndarray/base/nans-like`
**Body**: Review `@stdlib/ndarray/base/nans-like`. This package does not yet exist and must be created.

## Acceptance Criteria
- [x] `lib/main.js` — implements `nansLike(x)`, returns NaN-filled ndarray with same shape/dtype/order as input
- [x] `lib/index.js` — module wiring
- [x] `test/test.js` — tests covering all floating-point+generic dtypes (base and non-base), zero-dimensional arrays, empty arrays, and error case for unrecognized dtypes and integer dtypes
- [x] `examples/index.js` — runnable example iterating over supported dtypes
- [x] `benchmark/benchmark.js` — per-dtype benchmarks (float64, float32, complex128, complex64, generic)
- [x] `benchmark/benchmark.size.float64.js` through `*.generic.js` — size-varying benchmarks for each supported dtype
- [x] `docs/repl.txt` — REPL documentation
- [x] `docs/types/index.d.ts` — TypeScript declarations with overloads for each supported dtype
- [x] `docs/types/test.ts` — TypeScript type tests
- [x] `README.md` — package documentation
- [x] `package.json` — correct package metadata
- [x] All sanity checks pass (tape not installed; verified with direct node execution)
- [x] Namespace index.js and types/index.d.ts updated

## Key Design Decisions
- Only supports floating-point and generic dtypes (float64, float32, complex128, complex64, generic)
- Complex types use `CNAN` from `@stdlib/constants/complex128/nan`; others use `NaN`
- Uses `emptyLike` + `fill` pattern (like `ones-like`)
- Integer dtypes throw at runtime (fill throws TypeError for NaN + integer types)
- TypeScript uses per-dtype overloads (not generic pattern) since integer types throw
- No `@throws` annotation in JSDoc (match `ones-like` convention)

## Branch
`claude/vibrant-brahmagupta-jUurQ`

## Files Touched
- `lib/node_modules/@stdlib/ndarray/base/nans-like/` (new package, all files)
- `lib/node_modules/@stdlib/ndarray/base/lib/index.js` (added nansLike export)
- `lib/node_modules/@stdlib/ndarray/base/docs/types/index.d.ts` (added nansLike declaration)

## Iteration 1 — Plan: Implement
Created all package files for `@stdlib/ndarray/base/nans-like`.

## Iteration 1 — Review Findings

### Agent A (Correctness): Running
### Agent B (Test Quality): Completed
- BLOCKER F-9: Tests used pre-NaN inputs — aliasing bug would pass → FIXED: now use zeros() as input + buffer identity assertions
- BLOCKER F-5: Integer dtypes not tested → FIXED: added tests for int32/uint32/int16/uint16/int8/uint8/uint8c (all throw)
- MAJOR F-2: Buffer length not asserted → FIXED
- MAJOR F-3: Complex buffer length missing in non-base → FIXED
- MAJOR F-6: 0-dim only tested with generic → FIXED: added float64/float32/complex128/complex64
- MAJOR F-7: Empty array only tested with generic → FIXED: added float64 base test
- MINOR F-1: allNaN helper vacuously true for empty → FIXED: added guard
- MINOR F-12: Dead `expected` var in complex128 base test → FIXED (removed unused var)

### Agent C (Code Quality): Completed
- BLOCKER: @throws annotation incorrect (delegates to emptyLike, not direct throw) → FIXED: removed @throws, matches ones-like pattern
- MAJOR: TypeScript should use generic pattern `<T extends typedndarray<...>>` → DISPUTED: per-overload is correct because integer types throw (runtime verified)
- MINOR: getDType import "extra" compared to ones-like → ACCEPTED: needed for complex check, not a bug

### Agent D (Security): Running
### Agent E (Issue-Scope): Completed — No issues (everything is in scope)

## Triage

### Fixed
- Removed @throws from JSDoc (was inaccurate for "unrecognized dtype" framing; matches ones-like)
- Test rewrites: non-NaN inputs, buffer identity, buffer length, integer dtypes, 0-dim for all types
- allNaN helper guards empty arrays

### Disputed
- TypeScript generic vs per-overload: Per-overload KEPT. Reason: integer ndarray inputs to nansLike throw TypeError at runtime (fill rejects NaN for int types). The per-overload pattern correctly documents supported types. Generic `<T extends typedndarray<number | ComplexLike>>` would incorrectly accept integer ndarrays at the TypeScript level. The reviewer's pattern applies to ones-like which supports ALL dtypes; nans-like is more restrictive.

## Decision Log
1. Used emptyLike + fill pattern (like ones-like), not manual buffer pattern (like zeros-like)
2. No @throws in JSDoc — removed to match ones-like convention
3. TypeScript: per-dtype overloads (5 overloads) not generic — correctly restricts to NaN-capable types
4. Integer dtype tests: verified they DO throw (TypeError from fill), added throw tests
5. Tests use zeros() as input, not nans(), to make NaN filling visible

## Make Commands
- Tests: node script with NODE_PATH=/home/user/stdlib/lib/node_modules
- Examples: NODE_PATH=... node examples/index.js
26 changes: 26 additions & 0 deletions lib/node_modules/@stdlib/ndarray/base/docs/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ import minUnsignedIntegerDataType = require( '@stdlib/ndarray/base/min-unsigned-
import minViewBufferIndex = require( '@stdlib/ndarray/base/min-view-buffer-index' );
import minmaxViewBufferIndex = require( '@stdlib/ndarray/base/minmax-view-buffer-index' );
import nans = require( '@stdlib/ndarray/base/nans' );
import nansLike = require( '@stdlib/ndarray/base/nans-like' );
import ndarraylike2ndarray = require( '@stdlib/ndarray/base/ndarraylike2ndarray' );
import ndarraylike2object = require( '@stdlib/ndarray/base/ndarraylike2object' );
import ndarraylike2scalar = require( '@stdlib/ndarray/base/ndarraylike2scalar' );
Expand Down Expand Up @@ -2782,6 +2783,31 @@ interface Namespace {
*/
nans: typeof nans;

/**
* Creates a NaN-filled array having the same shape and data type as a provided input ndarray.
*
* @param x - input array
* @returns NaN-filled array
*
* @example
* var getShape = require( '@stdlib/ndarray/shape' );
* var getDType = require( '@stdlib/ndarray/dtype' );
* var nans = require( '@stdlib/ndarray/base/nans' );
*
* var x = nans( 'float64', [ 2, 2 ], 'row-major' );
* // returns <ndarray>[ [ NaN, NaN ], [ NaN, NaN ] ]
*
* var y = ns.nansLike( x );
* // returns <ndarray>[ [ NaN, NaN ], [ NaN, NaN ] ]
*
* var sh = getShape( y );
* // returns [ 2, 2 ]
*
* var dt = String( getDType( y ) );
* // returns 'float64'
*/
nansLike: typeof nansLike;

/**
* Converts an ndarray-like object to an ndarray.
*
Expand Down
9 changes: 9 additions & 0 deletions lib/node_modules/@stdlib/ndarray/base/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,15 @@ setReadOnly( ns, 'minmaxViewBufferIndex', require( '@stdlib/ndarray/base/minmax-
*/
setReadOnly( ns, 'nans', require( '@stdlib/ndarray/base/nans' ) );

/**
* @name nansLike
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/ndarray/base/nans-like}
*/
setReadOnly( ns, 'nansLike', require( '@stdlib/ndarray/base/nans-like' ) );

/**
* @name ndarraylike2ndarray
* @memberof ns
Expand Down
139 changes: 139 additions & 0 deletions lib/node_modules/@stdlib/ndarray/base/nans-like/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<!--

@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.

-->

# nansLike

> Create a NaN-filled [ndarray][@stdlib/ndarray/base/ctor] having the same shape and [data type][@stdlib/ndarray/dtypes] as a provided ndarray.

<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->

<section class="intro">

</section>

<!-- /.intro -->

<!-- Package usage documentation. -->

<section class="usage">

## Usage

```javascript
var nansLike = require( '@stdlib/ndarray/base/nans-like' );
```

#### nansLike( x )

Creates a NaN-filled [ndarray][@stdlib/ndarray/base/ctor] having the same shape and [data type][@stdlib/ndarray/dtypes] as a provided ndarray.

```javascript
var getShape = require( '@stdlib/ndarray/shape' );
var nans = require( '@stdlib/ndarray/base/nans' );

var x = nans( 'float64', [ 2, 2 ], 'row-major' );
// returns <ndarray>[ [ NaN, NaN ], [ NaN, NaN ] ]

var y = nansLike( x );
// returns <ndarray>[ [ NaN, NaN ], [ NaN, NaN ] ]

var sh = getShape( y );
// returns [ 2, 2 ]
```

</section>

<!-- /.usage -->

<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->

<section class="notes">

## Notes

- Along with data type, shape, and order, the function infers the "class" of the returned ndarray from the provided ndarray. For example, if provided a "base" [ndarray][@stdlib/ndarray/base/ctor], the function returns a base [ndarray][@stdlib/ndarray/base/ctor]. If provided a non-base [ndarray][@stdlib/ndarray/ctor], the function returns a non-base [ndarray][@stdlib/ndarray/ctor].

</section>

<!-- /.notes -->

<!-- Package usage examples. -->

<section class="examples">

## Examples

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

```javascript
var nans = require( '@stdlib/ndarray/base/nans' );
var ndarray2array = require( '@stdlib/ndarray/to-array' );
var nansLike = require( '@stdlib/ndarray/base/nans-like' );

var dt = [
'float64',
'float32',
'complex128',
'complex64',
'generic'
];

// Generate NaN-filled arrays...
var x;
var i;
for ( i = 0; i < dt.length; i++ ) {
x = nansLike( nans( dt[ i ], [ 2, 2 ], 'row-major' ) );
console.log( ndarray2array( x ) );
}
```

</section>

<!-- /.examples -->

<!-- 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. -->

<section class="references">

</section>

<!-- /.references -->

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

<section class="related">

</section>

<!-- /.related -->

<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->

<section class="links">

[@stdlib/ndarray/base/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/ctor

[@stdlib/ndarray/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/ctor

[@stdlib/ndarray/dtypes]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/dtypes

</section>

<!-- /.links -->
Loading