feat: add blas/ext/circshift#11189
Conversation
---
type: pre_commit_static_analysis_report
description: Results of running static analysis checks when committing changes.
report:
- task: lint_filenames
status: passed
- task: lint_editorconfig
status: passed
- task: lint_markdown
status: passed
- task: lint_package_json
status: passed
- task: lint_repl_help
status: passed
- task: lint_javascript_src
status: passed
- task: lint_javascript_cli
status: na
- task: lint_javascript_examples
status: passed
- task: lint_javascript_tests
status: passed
- task: lint_javascript_benchmarks
status: passed
- task: lint_python
status: na
- task: lint_r
status: na
- task: lint_c_src
status: na
- task: lint_c_examples
status: na
- task: lint_c_benchmarks
status: na
- task: lint_c_tests_fixtures
status: na
- task: lint_shell
status: na
- task: lint_typescript_declarations
status: passed
- task: lint_typescript_tests
status: passed
- task: lint_license_headers
status: passed
---
Coverage Report
The above coverage report was generated for the changes in this PR. |
| /** | ||
| * Circularly shifts the elements of an input ndarray along one or more ndarray dimensions by a specified number of positions. | ||
| */ | ||
| type Circshift = <T = unknown>( x: typedndarray<T>, k: K, options?: Options ) => typedndarray<T>; |
There was a problem hiding this comment.
This is not how we document packages which export a function. See
.There was a problem hiding this comment.
There is no need for a dedicated type.
There was a problem hiding this comment.
Furthermore, this definition is not correct. You are losing type information. This is a recurring theme for you in TS definitions; it would be good to upskill a bit here.
There was a problem hiding this comment.
Given that this function returns the input ndarray, the output value should preserve the specific type of the input ndarray.
| /** | ||
| * Number of positions to shift. | ||
| */ | ||
| type K = integerndarray | number; |
There was a problem hiding this comment.
| type K = integerndarray | number; | |
| type K = typedndarray<number> | number; |
There is no need to limit to ndarrays having integer dtypes.
| * @param x - input ndarray | ||
| * @param k - number of positions to shift | ||
| * @param options - function options | ||
| * @returns output ndarray |
There was a problem hiding this comment.
| * @returns output ndarray | |
| * @returns input ndarray |
| circshift( x, 2 ); // $ExpectType typedndarray<number> | ||
| circshift( x, 2, {} ); // $ExpectType typedndarray<number> |
There was a problem hiding this comment.
The tests need to be updated here.
| A positive `k` shifts elements to the right (toward higher indices). A | ||
| negative `k` shifts elements to the left (toward lower indices). If `k` is | ||
| zero, the input ndarray is left unchanged. |
There was a problem hiding this comment.
The language of "higher" and "lower" indices only makes sense in the case where dims refers to a single dimension. What about when you shift over multiple dimensions?
If you want to keep this language, you could say something like
| A positive `k` shifts elements to the right (toward higher indices). A | |
| negative `k` shifts elements to the left (toward lower indices). If `k` is | |
| zero, the input ndarray is left unchanged. | |
| When shifting elements along a single dimension, a positive `k` shifts elements to the right (toward higher indices), and a negative `k` shifts elements to the left (toward lower indices). | |
| If `k` is zero, the input ndarray is left unchanged. |
|
|
||
| k: ndarray|number | ||
| Number of positions to shift. May be either a scalar value or an | ||
| ndarray having an integer data type. If provided an ndarray, the value |
There was a problem hiding this comment.
| ndarray having an integer data type. If provided an ndarray, the value | |
| ndarray having a real-valued or "generic" data type. If provided an ndarray, the value |
|
|
||
| 'use strict'; | ||
|
|
||
| var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); |
There was a problem hiding this comment.
Use random/discrete-uniform. We don't need to be doing the whole random/array, new ndarray dance. For future examples, especially for top-level packages, prefer using the more concise APIs.
| // VARIABLES // | ||
|
|
||
| var idtypes0 = dtypes( 'all' ); // input ndarray | ||
| var idtypes1 = dtypes( 'integer' ); // k ndarray |
There was a problem hiding this comment.
| var idtypes1 = dtypes( 'integer' ); // k ndarray | |
| var idtypes1 = dtypes( 'real_and_generic' ); // k ndarray |
There was a problem hiding this comment.
You'll need to realign comments.
| 'use strict'; | ||
|
|
||
| /** | ||
| * Circularly shift the elements of an input ndarray along one or more ndarray dimensions by a specified number of positions. |
There was a problem hiding this comment.
| * Circularly shift the elements of an input ndarray along one or more ndarray dimensions by a specified number of positions. | |
| * Circularly shift the elements of an input ndarray by a specified number of positions along one or more ndarray dimensions. |
Applies here and everywhere else in this PR.
| // Case: circshift( x, k ) | ||
| if ( nargs === 2 ) { | ||
| // Case: circshift( x, k_scalar ) | ||
| if ( isNumber( o ) ) { |
There was a problem hiding this comment.
Why are you only enforcing isNumber here? Can we not use isInteger, instead?
There was a problem hiding this comment.
There's obviously a bit of tension with enforcing an integer k, but allowing any real-valued ndarray, but that should be fine for now. What we want to avoid is disallowing things like providing a "generic" ndarray, and we don't atm want to be in the game of having to perform a bunch of element-wise validation. The dominant use case will be an integer k, so I think it is fine to be a bit more strict here for that scenario.
| } | ||
| }); | ||
|
|
||
| tape( 'the function throws an error if provided a `k` argument which is not an ndarray-like object or a numeric scalar (options)', function test( t ) { |
There was a problem hiding this comment.
The use of "numeric scalar" should be updated here and elsewhere. It should be "integer".
| expected = [ 4.0, 1.0, 2.0, 3.0 ]; | ||
|
|
||
| t.strictEqual( actual, x, 'returns expected value' ); | ||
| t.strictEqual( getDType( actual ), 'generic', 'returns expected value' ); |
There was a problem hiding this comment.
This is incorrect. To test for dtype equality like this, you always need to do
| t.strictEqual( getDType( actual ), 'generic', 'returns expected value' ); | |
| t.strictEqual( String( getDType( actual ) ), 'generic', 'returns expected value' ); |
Applies here and elsewhere.
| tape( 'the function supports typed array inputs', function test( t ) { | ||
| var expected; | ||
| var actual; | ||
| var xbuf; | ||
| var x; | ||
|
|
||
| xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); | ||
| x = new ndarray( 'float64', xbuf, [ 6 ], [ 1 ], 0, 'row-major' ); | ||
|
|
||
| actual = circshift( x, 2 ); | ||
| expected = new Float64Array( [ 5.0, 6.0, 1.0, 2.0, 3.0, 4.0 ] ); | ||
|
|
||
| t.strictEqual( actual, x, 'returns expected value' ); | ||
| t.strictEqual( getDType( actual ), 'float64', 'returns expected value' ); | ||
| t.strictEqual( isSameFloat64Array( getData( actual ), expected ), true, 'returns expected value' ); | ||
|
|
||
| xbuf = new Float32Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); | ||
| x = new ndarray( 'float32', xbuf, [ 6 ], [ 1 ], 0, 'row-major' ); | ||
|
|
||
| actual = circshift( x, 2 ); | ||
| expected = new Float32Array( [ 5.0, 6.0, 1.0, 2.0, 3.0, 4.0 ] ); | ||
|
|
||
| t.strictEqual( actual, x, 'returns expected value' ); | ||
| t.strictEqual( getDType( actual ), 'float32', 'returns expected value' ); | ||
| t.strictEqual( isSameFloat32Array( getData( actual ), expected ), true, 'returns expected value' ); | ||
|
|
||
| t.end(); | ||
| }); |
There was a problem hiding this comment.
Remove this. This is not needed.
| t.end(); | ||
| }); | ||
|
|
||
| tape( 'the function supports large shift values (k > N)', function test( t ) { |
There was a problem hiding this comment.
| tape( 'the function supports large shift values (k > N)', function test( t ) { | |
| tape( 'the function supports large shift values (|k| > N)', function test( t ) { |
| The function has the following parameters: | ||
|
|
||
| - **x**: input [ndarray][@stdlib/ndarray/ctor]. | ||
| - **k**: number of positions to shift. May be either a numeric scalar value or an [ndarray][@stdlib/ndarray/ctor] having an integer [data type][@stdlib/ndarray/dtypes]. If provided an [ndarray][@stdlib/ndarray/ctor], the value must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the complement of the shape defined by `options.dims`. For example, given the input shape `[2, 3, 4]` and `options.dims=[0]`, an [ndarray][@stdlib/ndarray/ctor] for `k` must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the shape `[3, 4]`. Similarly, when performing the operation over all elements in a provided input [ndarray][@stdlib/ndarray/ctor], an [ndarray][@stdlib/ndarray/ctor] for `k` must be a zero-dimensional [ndarray][@stdlib/ndarray/ctor]. |
There was a problem hiding this comment.
| - **k**: number of positions to shift. May be either a numeric scalar value or an [ndarray][@stdlib/ndarray/ctor] having an integer [data type][@stdlib/ndarray/dtypes]. If provided an [ndarray][@stdlib/ndarray/ctor], the value must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the complement of the shape defined by `options.dims`. For example, given the input shape `[2, 3, 4]` and `options.dims=[0]`, an [ndarray][@stdlib/ndarray/ctor] for `k` must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the shape `[3, 4]`. Similarly, when performing the operation over all elements in a provided input [ndarray][@stdlib/ndarray/ctor], an [ndarray][@stdlib/ndarray/ctor] for `k` must be a zero-dimensional [ndarray][@stdlib/ndarray/ctor]. | |
| - **k**: number of positions to shift. May be either an integer scalar value or an [ndarray][@stdlib/ndarray/ctor] having a real-valued or "generic" [data type][@stdlib/ndarray/dtypes]. If provided an [ndarray][@stdlib/ndarray/ctor], the value must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the complement of the shape defined by `options.dims`. For example, given the input shape `[2, 3, 4]` and `options.dims=[0]`, an [ndarray][@stdlib/ndarray/ctor] for `k` must have a shape which is [broadcast-compatible][@stdlib/ndarray/base/broadcast-shapes] with the shape `[3, 4]`. Similarly, when performing the operation over all elements in a provided input [ndarray][@stdlib/ndarray/ctor], an [ndarray][@stdlib/ndarray/ctor] for `k` must be a zero-dimensional [ndarray][@stdlib/ndarray/ctor]. |
| ## Notes | ||
|
|
||
| - The input [ndarray][@stdlib/ndarray/ctor] is shifted **in-place** (i.e., the input [ndarray][@stdlib/ndarray/ctor] is **mutated**). | ||
| - A positive `k` shifts elements to the right (toward higher indices). A negative `k` shifts elements to the left (toward lower indices). If `k` is zero, the input [ndarray][@stdlib/ndarray/ctor] is left unchanged. |
| <!-- eslint no-undef: "error" --> | ||
|
|
||
| ```javascript | ||
| var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); |
kgryte
left a comment
There was a problem hiding this comment.
Initial review. This PR needs quite a bit of clean-up.
|
For METR, |
type: pre_commit_static_analysis_report
description: Results of running static analysis checks when committing changes. report:
Resolves stdlib-js/metr-issue-tracker#257.
Description
This pull request:
blas/ext/base/circshiftRelated Issues
This pull request has the following related issues:
blas/ext/circshiftmetr-issue-tracker#257Questions
No.
Other
No.
Checklist
AI Assistance
If you answered "yes" above, how did you use AI assistance?
Disclosure
Primarily written by Claude Code. Note: AI incorrectly created a malformed test file, and hallucinated a bit with the typescript declarations.
@stdlib-js/reviewers