Skip to content

Commit e57ccb2

Browse files
committed
refactor: update boolean array indexing implementation and add tests
1 parent d903fc9 commit e57ccb2

File tree

5 files changed

+3107
-58
lines changed

5 files changed

+3107
-58
lines changed

lib/node_modules/@stdlib/array/to-fancy/lib/set_elements.js

+22-9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var scalar2array = require( '@stdlib/array/from-scalar' );
2626
var dtype = require( '@stdlib/array/dtype' );
2727
var put = require( '@stdlib/array/put' );
2828
var where = require( '@stdlib/array/base/where' ).assign;
29+
var place = require( '@stdlib/array/base/place' );
2930
var format = require( '@stdlib/string/format' );
3031
var prop2array = require( './prop2array.js' );
3132
var errMessage = require( './error_message.js' );
@@ -53,20 +54,20 @@ var errMessage = require( './error_message.js' );
5354
* @returns {boolean} boolean indicating whether assignment succeeded
5455
*/
5556
function setElements( target, property, value, ctx ) {
57+
var tdt;
58+
var vdt;
5659
var idx;
5760
var err;
58-
var dt;
5961
var v;
6062

6163
idx = prop2array( property, ctx.cache );
64+
tdt = ctx.dtype || 'generic';
6265
if ( isCollection( value ) ) {
6366
// When handling collections, we delegate to implementation APIs (see below) to perform argument validation (e.g., ensuring a (mostly) safe cast, broadcast compatibility, etc), so we just reassign the value here:
6467
v = value;
65-
dt = dtype( value ) || 'generic';
6668
} else {
6769
// When provided a "scalar", we need to check whether the value can be safely cast to the target array data type:
68-
dt = ctx.dtype;
69-
err = ctx.validator( value, dt );
70+
err = ctx.validator( value, tdt );
7071
if ( err ) {
7172
throw err;
7273
}
@@ -76,7 +77,8 @@ function setElements( target, property, value, ctx ) {
7677
v = value;
7778
}
7879
// As the scalar can be safely cast, convert the scalar to an array having the same data type as the target array to allow for broadcasting during assignment:
79-
v = scalar2array( v, dt );
80+
v = scalar2array( v, tdt );
81+
vdt = tdt;
8082
}
8183
if ( idx.type === 'int' ) {
8284
try {
@@ -86,16 +88,27 @@ function setElements( target, property, value, ctx ) {
8688
}
8789
return true;
8890
}
91+
if ( vdt === void 0 ) {
92+
vdt = dtype( value ) || 'generic';
93+
}
8994
// Safe casts are always allowed and allow same kind casts (i.e., downcasts) only when the target array data type is floating-point...
90-
if ( !isMostlySafeCast( dt, ctx.dtype ) ) {
91-
throw new TypeError( format( 'invalid operation. Assigned value cannot be safely cast to the target array data type. Data types: [%s, %s].', dt, ctx.dtype ) );
95+
if ( !isMostlySafeCast( vdt, tdt ) ) {
96+
throw new TypeError( format( 'invalid operation. Assigned value cannot be safely cast to the target array data type. Data types: [%s, %s].', vdt, tdt ) );
9297
}
9398
if ( idx.type === 'bool' ) {
94-
where( idx.data, v, target, target, 1, 0 );
99+
try {
100+
place( target, idx.data, v, 'strict_broadcast' );
101+
} catch ( err ) {
102+
throw new err.constructor( errMessage( err.message ) );
103+
}
95104
return true;
96105
}
97106
if ( idx.type === 'mask' ) {
98-
where( idx.data, target, v, target, 1, 0 );
107+
try {
108+
where( idx.data, target, v, target, 1, 0 ); // note: intentionally deviate from boolean array indexing here and interpret the mask as applying to both the target and values array, thus requiring that the assigned value array be broadcast compatible with the target array and NOT just the selected elements as in boolean array indexing
109+
} catch ( err ) {
110+
throw new err.constructor( errMessage( err.message ) );
111+
}
99112
return true;
100113
}
101114
throw new Error( format( 'invalid operation. Unrecognized array index type. Value: `%s`.', idx.type ) );

lib/node_modules/@stdlib/array/to-fancy/lib/set_slice.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function setSlice( target, property, value, receiver, ctx ) {
6868
throw err;
6969
}
7070
// As the scalar can be safely cast, convert the scalar to an array having the same data type as the target array to allow for broadcasting during slice assignment:
71-
v = scalar2array( value, ctx.dtype );
71+
v = scalar2array( value, ctx.dtype || 'generic' );
7272
}
7373
try {
7474
sliceAssign( v, receiver, s, ctx.strict );

0 commit comments

Comments
 (0)