All files / base/fancy-slice-assign/lib main.js

62.4% Statements 83/133
100% Branches 1/1
0% Functions 0/1
62.4% Lines 83/133

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 1341x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                     1x 1x 1x 1x 1x  
/**
* @license Apache-2.0
*
* Copyright (c) 2024 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.
*/
 
'use strict';
 
// MODULES //
 
var isMostlySafeCast = require( '@stdlib/array/base/assert/is-mostly-safe-data-type-cast' );
var isRealDataType = require( '@stdlib/array/base/assert/is-real-data-type' );
var isComplexDataType = require( '@stdlib/array/base/assert/is-complex-floating-point-data-type' );
var normalizeSlice = require( '@stdlib/slice/base/normalize-slice' );
var sliceLength = require( '@stdlib/slice/base/length' );
var dtype = require( '@stdlib/array/dtype' );
var convert = require( '@stdlib/array/convert' );
var gcopy = require( '@stdlib/blas/base/gcopy' ).ndarray;
var format = require( '@stdlib/string/format' );
 
 
// MODULES //
 
/**
* Assigns element values from a broadcasted input array to corresponding elements in an output array.
*
* @param {Collection} x - input array
* @param {Collection} y - output array
* @param {Slice} s - slice object
* @param {boolean} strict - boolean indicating whether to enforce strict bounds checking
* @throws {RangeError} slice exceeds array bounds
* @throws {Error} input array must be broadcast compatible with an output array view
* @throws {TypeError} input array cannot be safely cast to the output array data type
* @returns {Collection} output array
*
* @example
* var Slice = require( '@stdlib/slice/ctor' );
*
* var x = [ 1, 2, 3, 4 ];
* var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
*
* var s = new Slice( null, null, -2 );
* // returns <Slice>
*
* var out = sliceAssign( x, y, s, false );
* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ]
*
* var bool = ( out === y );
* // returns true
*
* @example
* var Int32Array = require( '@stdlib/array/int32' );
* var Slice = require( '@stdlib/slice/ctor' );
*
* var x = new Int32Array( [ 5 ] );
* var y = new Int32Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] );
*
* var s = new Slice( null, null, -2 );
* // returns <Slice>
*
* var out = sliceAssign( x, y, s, false );
* // returns <Int32Array>[ 0, 5, 0, 5, 0, 5, 0, 5 ]
*
* var bool = ( out === y );
* // returns true
*/
function sliceAssign( x, y, s, strict ) {
	var xlen;
	var ylen;
	var xdt;
	var ydt;
	var ns;
	var xs;
	var N;

	xdt = dtype( x ) || 'generic';
	ydt = dtype( y ) || 'generic';

	xlen = x.length;
	ylen = y.length;

	// Safe casts are always allowed and allow same kind casts (i.e., downcasts) only when the output data type is floating-point...
	if ( !isMostlySafeCast( xdt, ydt ) ) {
		throw new TypeError( format( 'invalid argument. Input array values cannot be safely cast to the output array data type. Data types: [%s, %s].', xdt, ydt ) );
	}
	// When performing a real-to-complex assignment, interpret the real-valued array as containing real components with implied imaginary components equal to zero and explicitly convert to a complex-valued array...
	if ( isComplexDataType( ydt ) && isRealDataType( xdt ) ) {
		x = convert( x, ydt );
	}
	// Normalize the slice object base on the output array length:
	ns = normalizeSlice( s, ylen, true );

	// Check whether the slice exceeds the array bounds...
	if ( ns.code ) {
		if ( strict ) {
			throw new RangeError( format( 'invalid argument. Slice exceeds array bounds. Array length: %d.', ylen ) );
		}
		// Normalize again, this time allowing for out-of-bounds indices:
		ns = normalizeSlice( s, ylen, false );
	}
	// Compute the slice length:
	N = sliceLength( ns );

	// Broadcast the input array:
	if ( xlen === 1 ) {
		xs = 0;
	} else if ( xlen === N ) {
		xs = 1;
	} else {
		throw new Error( format( 'invalid argument. Input array and the output array slice are broadcast incompatible. Array length: %u. Desired length: %u.', xlen, N ) );
	}
	// Copy elements to the output array:
	gcopy( N, x, xs, 0, y, ns.step, ns.start );

	return y;
}
 
 
// EXPORTS //
 
module.exports = sliceAssign;