Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ limitations under the License.
var removeSingletonDimensions = require( '@stdlib/ndarray/base/remove-singleton-dimensions' );
```

#### removeSingletonDimensions( x )
#### removeSingletonDimensions( x, writable )

Returns an ndarray without singleton dimensions (i.e., dimensions whose size is equal to `1`).

Expand All @@ -49,16 +49,18 @@ var array = require( '@stdlib/ndarray/array' );

// Create a 1x2x2 ndarray:
var x = array( [ [ [ 1, 2 ], [ 3, 4 ] ] ] );
// returns <ndarray>
// returns <ndarray>[ [ [ 1, 2 ], [ 3, 4 ] ] ]

// Remove singleton dimensions:
var y = removeSingletonDimensions( x );
// returns <ndarray>

var sh = y.shape;
// returns [ 2, 2 ]
var y = removeSingletonDimensions( x, false );
// returns <ndarray>[ [ 1, 2 ], [ 3, 4 ] ]
```

The function accepts the following arguments:

- **x**: input ndarray.
- **writable**: boolean indicating whether a returned ndarray should be writable.
Copy link
Member

Choose a reason for hiding this comment

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

This parameter is somewhat in conflict with the note at L74. Namely, if we return a provided ndarray unchanged, then the writable parameter is ignored.

Copy link
Member

@kgryte kgryte Jan 10, 2026

Choose a reason for hiding this comment

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

We have a couple of choices. 1) Always return a new view of the input ndarray. 2) Update the docs here to indicate that the writable parameter will be ignored if the input ndarray doesn't have any singleton dimensions. 3) Pursue (1) plus add the package maybe-remove-singleton-dimensions where this new package does what this package does now, which is returns an input ndarray unchanged iff an input ndarray has no singleton dimensions.

The original rationale for sometimes returning the original input ndarray is for performance, as ndarray view creation is expensive. Having a maybe-* prefix makes this behavior explicit similar to maybe-broadcast-array, etc.

That seem reasonable to you, @headlessNode?

Copy link
Member Author

Choose a reason for hiding this comment

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

@kgryte So, we add a maybe- prefix to this package and add the remove-singleton-dimensions package which always return a new view?

Copy link
Member

Choose a reason for hiding this comment

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

@headlessNode That doesn't quite make sense. It means copy the current package to maybe-* and then modify the existing package to always return a view.

Copy link
Member

Choose a reason for hiding this comment

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

Also means that we'll need a follow-up PR to migrate all current downstream usage to use the maybe-* package.

Copy link
Member Author

Choose a reason for hiding this comment

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

@kgryte I've modified the current package to always return a new view. I think adding the maybe-* package and updating downstream usage should be separate PR?

Copy link
Member

Choose a reason for hiding this comment

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

Correct. Adding and updating should actually be two separate PRs (in addition to the current PR).


</section>

<!-- /.usage -->
Expand All @@ -69,8 +71,7 @@ var sh = y.shape;

## Notes

- If a provided ndarray does not have any singleton dimensions, the function returns the provided ndarray unchanged.
- If a provided ndarray does have singleton dimensions, the function returns a new ndarray view.
- The function always returns a new view of the input ndarray.

</section>

Expand All @@ -85,33 +86,15 @@ var sh = y.shape;
<!-- eslint no-undef: "error" -->

```javascript
var array = require( '@stdlib/ndarray/array' );
var numel = require( '@stdlib/ndarray/base/numel' );
var ind2sub = require( '@stdlib/ndarray/ind2sub' );
var uniform = require( '@stdlib/random/uniform' );
var ndarray2array = require( '@stdlib/ndarray/to-array' );
var removeSingletonDimensions = require( '@stdlib/ndarray/base/remove-singleton-dimensions' );

// Create a 5-dimensional array:
var x = array( [ [ 1, 2 ], [ 3, 4 ] ], {
'ndmin': 5
});
// returns <ndarray>

// Remove singleton dimensions:
var y = removeSingletonDimensions( x );
// returns <ndarray>

// Retrieve the shape:
var sh = y.shape;
// returns [ 2, 2 ]

// Retrieve the number of elements:
var N = numel( sh );
var x = uniform( [ 1, 1, 3, 3, 3 ], -10.0, 10.0 );
console.log( ndarray2array( x ) );

// Loop through the array elements...
var i;
for ( i = 0; i < N; i++ ) {
console.log( 'Y[%s] = %d', ind2sub( sh, i ).join( ', ' ), y.iget( i ) );
}
var y = removeSingletonDimensions( x, false );
console.log( ndarray2array( y ) );
```

</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ var Float64Array = require( '@stdlib/array/float64' );
var ndarrayBase = require( '@stdlib/ndarray/base/ctor' );
var ndarray = require( '@stdlib/ndarray/ctor' );
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var format = require( '@stdlib/string/format' );
var pkg = require( './../package.json' ).name;
var removeSingletonDimensions = require( './../lib' );


// MAIN //

bench( pkg+'::base_ndarray,2d', function benchmark( b ) {
bench( format( '%s::base_ndarray,2d', pkg ), function benchmark( b ) {
var strides;
var values;
var buffer;
Expand Down Expand Up @@ -59,7 +60,7 @@ bench( pkg+'::base_ndarray,2d', function benchmark( b ) {

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = removeSingletonDimensions( values[ i%values.length ] );
out = removeSingletonDimensions( values[ i%values.length ], false );
if ( typeof out !== 'object' ) {
b.fail( 'should return an object' );
}
Expand All @@ -72,7 +73,7 @@ bench( pkg+'::base_ndarray,2d', function benchmark( b ) {
b.end();
});

bench( pkg+'::base_ndarray,2d,no_singleton_dimensions', function benchmark( b ) {
bench( format( '%s::base_ndarray,2d,no_singleton_dimensions', pkg ), function benchmark( b ) {
var strides;
var values;
var buffer;
Expand Down Expand Up @@ -100,7 +101,7 @@ bench( pkg+'::base_ndarray,2d,no_singleton_dimensions', function benchmark( b )

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = removeSingletonDimensions( values[ i%values.length ] );
out = removeSingletonDimensions( values[ i%values.length ], false );
if ( typeof out !== 'object' ) {
b.fail( 'should return an object' );
}
Expand All @@ -113,7 +114,7 @@ bench( pkg+'::base_ndarray,2d,no_singleton_dimensions', function benchmark( b )
b.end();
});

bench( pkg+'::ndarray,2d', function benchmark( b ) {
bench( format( '%s::ndarray,2d', pkg ), function benchmark( b ) {
var strides;
var values;
var buffer;
Expand Down Expand Up @@ -141,7 +142,7 @@ bench( pkg+'::ndarray,2d', function benchmark( b ) {

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = removeSingletonDimensions( values[ i%values.length ] );
out = removeSingletonDimensions( values[ i%values.length ], false );
if ( typeof out !== 'object' ) {
b.fail( 'should return an object' );
}
Expand All @@ -154,7 +155,7 @@ bench( pkg+'::ndarray,2d', function benchmark( b ) {
b.end();
});

bench( pkg+'::ndarray,2d,no_singleton_dimensions', function benchmark( b ) {
bench( format( '%s::ndarray,2d,no_singleton_dimensions', pkg ), function benchmark( b ) {
var strides;
var values;
var buffer;
Expand Down Expand Up @@ -182,7 +183,7 @@ bench( pkg+'::ndarray,2d,no_singleton_dimensions', function benchmark( b ) {

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = removeSingletonDimensions( values[ i%values.length ] );
out = removeSingletonDimensions( values[ i%values.length ], false );
if ( typeof out !== 'object' ) {
b.fail( 'should return an object' );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
var bench = require( '@stdlib/bench' );
var array = require( '@stdlib/ndarray/array' );
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var format = require( '@stdlib/string/format' );
var pkg = require( './../package.json' ).name;
var removeSingletonDimensions = require( './../lib' );

Expand Down Expand Up @@ -54,7 +55,7 @@ function createBenchmark( ndims ) {

b.tic();
for ( i = 0; i < b.iterations; i++ ) {
out = removeSingletonDimensions( x );
out = removeSingletonDimensions( x, false );
if ( typeof out !== 'object' ) {
b.fail( 'should return an object' );
}
Expand Down Expand Up @@ -87,7 +88,7 @@ function main() {

for ( i = min; i <= max; i++ ) {
f = createBenchmark( i );
bench( pkg+'::ndarray,2d:singleton_dimensions='+i, f );
bench( format( '%s::ndarray,2d:singleton_dimensions=%d', pkg, i ), f );
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@

{{alias}}( x )
{{alias}}( x, writable )
Returns an array without singleton dimensions.

If a provided ndarray does not have any singleton dimensions, the function
returns the provided ndarray unchanged.

If a provided ndarray does have singleton dimensions, the function returns a
new ndarray view.
The function always returns a new view of the input ndarray.

Parameters
----------
x: ndarray
Input array.

writable: boolean
Boolean indicating whether a returned array should be writable.

Returns
-------
out: ndarray
Expand All @@ -21,21 +20,9 @@
Examples
--------
> var x = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2 ], [ 3, 4 ] ], { 'ndmin': 5 } )
<ndarray>
> var sh = x.shape
[ 1, 1, 1, 2, 2 ]
> var y = {{alias}}( x )
<ndarray>
> sh = y.shape
[ 2, 2 ]
> var v = y.get( 0, 0 )
1
> v = y.get( 0, 1 )
2
> v = y.get( 1, 0 )
3
> v = y.get( 1, 1 )
4
<ndarray>[ [ [ [ [1, 2 ], [ 3, 4 ] ] ] ] ]
> var y = {{alias}}( x, false )
<ndarray>[ [ 1, 2 ], [ 3, 4 ] ]

See Also
--------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import { ndarray } from '@stdlib/types/ndarray';
*
* ## Notes
*
* - If a provided ndarray does not have any singleton dimensions, the function returns the provided ndarray unchanged.
* - If a provided ndarray does have singleton dimensions, the function returns a new ndarray view.
* - The function always returns a new view of the input ndarray.
*
* @param x - input array
* @param writable - boolean indicating whether a returned array should be writable
* @returns squeezed array
*
* @example
Expand All @@ -39,30 +39,12 @@ import { ndarray } from '@stdlib/types/ndarray';
* var x = array( [ [ 1, 2 ], [ 3, 4 ] ], {
* 'ndmin': 5
* });
* // returns <ndarray>
* // returns <ndarray>[ [ [ [ [ 1, 2 ], [ 3, 4 ] ] ] ] ]
*
* var shx = x.shape;
* // returns [ 1, 1, 1, 2, 2 ]
*
* var y = removeSingletonDimensions( x );
* // returns <ndarray>
*
* var shy = y.shape;
* // returns [ 2, 2 ]
*
* var v = y.get( 0, 0 );
* // returns 1
*
* v = y.get( 0, 1 );
* // returns 2
*
* v = y.get( 1, 0 );
* // returns 3
*
* v = y.get( 1, 1 );
* // returns 4
* var y = removeSingletonDimensions( x, false );
* // returns <ndarray>[ [ 1, 2 ], [ 3, 4 ] ]
*/
declare function removeSingletonDimensions( x: ndarray ): ndarray;
declare function removeSingletonDimensions( x: ndarray, writable: boolean ): ndarray;


// EXPORTS //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,38 @@ import removeSingletonDimensions = require( './index' );
{
const x = array( [ [ 1, 2 ], [ 3, 4 ] ] );

removeSingletonDimensions( x ); // $ExpectType ndarray
removeSingletonDimensions( x, false ); // $ExpectType ndarray
}

// The compiler throws an error if the function is not provided a first argument which is an ndarray...
{
removeSingletonDimensions( '5' ); // $ExpectError
removeSingletonDimensions( 5 ); // $ExpectError
removeSingletonDimensions( true ); // $ExpectError
removeSingletonDimensions( false ); // $ExpectError
removeSingletonDimensions( null ); // $ExpectError
removeSingletonDimensions( {} ); // $ExpectError
removeSingletonDimensions( [ '5' ] ); // $ExpectError
removeSingletonDimensions( ( x: number ): number => x ); // $ExpectError
removeSingletonDimensions( '5', false ); // $ExpectError
removeSingletonDimensions( 5, false ); // $ExpectError
removeSingletonDimensions( true, false ); // $ExpectError
removeSingletonDimensions( false, false ); // $ExpectError
removeSingletonDimensions( null, false ); // $ExpectError
removeSingletonDimensions( {}, false ); // $ExpectError
removeSingletonDimensions( [ '5' ], false ); // $ExpectError
removeSingletonDimensions( ( x: number ): number => x, false ); // $ExpectError
}

// The compiler throws an error if the function is not provided a second argument which is a boolean...
{
const x = array( [ [ 1, 2 ], [ 3, 4 ] ] );

removeSingletonDimensions( x, '5' ); // $ExpectError
removeSingletonDimensions( x, 5 ); // $ExpectError
removeSingletonDimensions( x, null ); // $ExpectError
removeSingletonDimensions( x, {} ); // $ExpectError
removeSingletonDimensions( x, [ '5' ] ); // $ExpectError
removeSingletonDimensions( x, ( x: number ): number => x ); // $ExpectError
}

// The compiler throws an error if the function is provided an unsupported number of arguments...
{
const x = array( [ [ 1, 2 ], [ 3, 4 ] ] );

removeSingletonDimensions(); // $ExpectError
removeSingletonDimensions( x, [ 1, 2, 3 ], [ 2, 3 ] ); // $ExpectError
removeSingletonDimensions( x ); // $ExpectError
removeSingletonDimensions( x, false, {} ); // $ExpectError
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,12 @@

'use strict';

var array = require( '@stdlib/ndarray/array' );
var numel = require( '@stdlib/ndarray/base/numel' );
var ind2sub = require( '@stdlib/ndarray/ind2sub' );
var uniform = require( '@stdlib/random/uniform' );
var ndarray2array = require( '@stdlib/ndarray/to-array' );
var removeSingletonDimensions = require( './../lib' );

// Create a 5-dimensional array:
var x = array( [ [ 1, 2 ], [ 3, 4 ] ], {
'ndmin': 5
});
// returns <ndarray>
var x = uniform( [ 1, 1, 3, 3, 3 ], -10.0, 10.0 );
console.log( ndarray2array( x ) );

// Remove singleton dimensions:
var y = removeSingletonDimensions( x );
// returns <ndarray>

// Retrieve the shape:
var sh = y.shape;
// returns [ 2, 2 ]

// Retrieve the number of elements:
var N = numel( sh );

// Loop through the array elements...
var i;
for ( i = 0; i < N; i++ ) {
console.log( 'Y[%s] = %d', ind2sub( sh, i ).join( ', ' ), y.iget( i ) );
}
var y = removeSingletonDimensions( x, false );
console.log( ndarray2array( y ) );
Loading