|
| 1 | +/** |
| 2 | +* @license Apache-2.0 |
| 3 | +* |
| 4 | +* Copyright (c) 2024 The Stdlib Authors. |
| 5 | +* |
| 6 | +* Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | +* you may not use this file except in compliance with the License. |
| 8 | +* You may obtain a copy of the License at |
| 9 | +* |
| 10 | +* http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +* |
| 12 | +* Unless required by applicable law or agreed to in writing, software |
| 13 | +* distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | +* See the License for the specific language governing permissions and |
| 16 | +* limitations under the License. |
| 17 | +*/ |
| 18 | + |
| 19 | +'use strict'; |
| 20 | + |
| 21 | +// MODULES // |
| 22 | + |
| 23 | +var isComplexDataType = require( '@stdlib/array/base/assert/is-complex-floating-point-data-type' ); |
| 24 | +var isBooleanDataType = require( '@stdlib/array/base/assert/is-boolean-data-type' ); |
| 25 | +var isComplexLike = require( '@stdlib/assert/is-complex-like' ); |
| 26 | +var Boolean = require( '@stdlib/boolean/ctor' ); |
| 27 | +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); |
| 28 | +var reinterpret = require( '@stdlib/strided/base/reinterpret-complex' ); |
| 29 | +var reinterpretBoolean = require( '@stdlib/strided/base/reinterpret-boolean' ); |
| 30 | +var normalizeIndex = require( '@stdlib/ndarray/base/normalize-index' ); |
| 31 | +var real = require( '@stdlib/complex/float64/real' ); |
| 32 | +var imag = require( '@stdlib/complex/float64/imag' ); |
| 33 | +var format = require( '@stdlib/string/format' ); |
| 34 | + |
| 35 | + |
| 36 | +// FUNCTIONS // |
| 37 | + |
| 38 | +/** |
| 39 | +* Copies elements from one array to another array and inserts the element at the specified index to a provided value. |
| 40 | +* |
| 41 | +* @private |
| 42 | +* @param {Collection} x - input array |
| 43 | +* @param {integer} index - element index |
| 44 | +* @param {*} value - inserting value |
| 45 | +* @param {Collection} out - output array |
| 46 | +* @param {integer} stride - output array stride |
| 47 | +* @param {NonNegativeInteger} offset - output array offset |
| 48 | +* @returns {Collection} output array |
| 49 | +* |
| 50 | +* @example |
| 51 | +* var x = [ 1, 2, 3, 4 ]; |
| 52 | +* |
| 53 | +* var out = [ 0, 0, 0, 0, 0 ]; |
| 54 | +* var arr = indexed( x, 0, 5, out, 1, 0 ); |
| 55 | +* // returns [ 5, 1, 2, 3, 4 ] |
| 56 | +* |
| 57 | +* var bool = ( arr === out ); |
| 58 | +* // returns true |
| 59 | +*/ |
| 60 | +function indexed( x, index, value, out, stride, offset ) { |
| 61 | + var io; |
| 62 | + var i; |
| 63 | + |
| 64 | + io = offset; |
| 65 | + for ( i = 0; i < x.length; i++ ) { |
| 66 | + out[ io ] = x[ i ]; |
| 67 | + io += stride; |
| 68 | + } |
| 69 | + for ( i = x.length - 1; i >= index; i-- ) { |
| 70 | + out[ offset + ((i + 1) * stride) ] = out[ offset + (i * stride) ]; |
| 71 | + } |
| 72 | + out[ offset + (index * stride) ] = value; |
| 73 | + |
| 74 | + return out; |
| 75 | +} |
| 76 | + |
| 77 | +/** |
| 78 | +* Copies elements from one accessor array to another accessor array and inserts the element at the specified index to a provided value. |
| 79 | +* |
| 80 | +* @private |
| 81 | +* @param {Object} x - input array object |
| 82 | +* @param {integer} index - element index |
| 83 | +* @param {*} value - inserting value |
| 84 | +* @param {Object} out - output array object |
| 85 | +* @param {integer} stride - output array stride |
| 86 | +* @param {NonNegativeInteger} offset - output array offset |
| 87 | +* @returns {Collection} output array |
| 88 | +* |
| 89 | +* @example |
| 90 | +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); |
| 91 | +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); |
| 92 | +* |
| 93 | +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); |
| 94 | +* |
| 95 | +* var out = toAccessorArray( [ 0, 0, 0, 0, 0 ] ); |
| 96 | +* var arr = accessors( arraylike2object( x ), 0, 5, arraylike2object( out ), 1, 0 ); |
| 97 | +* |
| 98 | +* var v = arr.get( 0 ); |
| 99 | +* // returns 5 |
| 100 | +*/ |
| 101 | +function accessors( x, index, value, out, stride, offset ) { |
| 102 | + var xdata; |
| 103 | + var odata; |
| 104 | + var xget; |
| 105 | + var oset; |
| 106 | + var io; |
| 107 | + var i; |
| 108 | + |
| 109 | + xdata = x.data; |
| 110 | + odata = out.data; |
| 111 | + |
| 112 | + xget = x.accessors[ 0 ]; |
| 113 | + oset = out.accessors[ 1 ]; |
| 114 | + |
| 115 | + io = offset; |
| 116 | + for ( i = 0; i < xdata.length; i++ ) { |
| 117 | + oset( odata, io, xget( xdata, i ) ); |
| 118 | + io += stride; |
| 119 | + } |
| 120 | + for ( i = xdata.length - 1; i >= index; i-- ) { |
| 121 | + oset( odata, offset + ((i + 1) * stride), xget( odata, offset + (i * stride) ) ); |
| 122 | + } |
| 123 | + |
| 124 | + oset( odata, offset + (index * stride), value ); |
| 125 | + return odata; |
| 126 | +} |
| 127 | + |
| 128 | +/** |
| 129 | +* Copies elements from one complex array to another complex array and inserts the element at the specified index to a provided value. |
| 130 | +* |
| 131 | +* @private |
| 132 | +* @param {Collection} x - real-valued floating-point input array view |
| 133 | +* @param {integer} index - element index |
| 134 | +* @param {ComplexLike} value - inserting value |
| 135 | +* @param {Collection} out - real-valued floating-point output array view |
| 136 | +* @param {integer} stride - output array stride |
| 137 | +* @param {NonNegativeInteger} offset - output array offset |
| 138 | +* @returns {Collection} output array view |
| 139 | +* |
| 140 | +* @example |
| 141 | +* var Complex128 = require( '@stdlib/complex/float64/ctor' ); |
| 142 | +* var Float64Array = require( '@stdlib/array/float64' ); |
| 143 | +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); |
| 144 | +* |
| 145 | +* var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); |
| 146 | +* |
| 147 | +* var out = new Float64Array( 6 ); |
| 148 | +* var arr = complex( x, 0, new Complex128( 5.0, 6.0 ), out, 1, 0 ); |
| 149 | +* // returns <Float64Array>[ 5.0, 6.0, 1.0, 2.0, 3.0, 4.0 ] |
| 150 | +*/ |
| 151 | +function complex( x, index, value, out, stride, offset ) { |
| 152 | + var so; |
| 153 | + var io; |
| 154 | + var i; |
| 155 | + |
| 156 | + so = stride * 2; // multiply by 2, as real-valued array consists of interleaved real and imaginary components |
| 157 | + io = offset * 2; |
| 158 | + for ( i = 0; i < x.length/2; i++ ) { |
| 159 | + out[ io + ( i * so ) ] = x[ 2 * i ]; |
| 160 | + out[ io + ( i * so ) + 1 ] = x[ ( 2 * i ) + 1 ]; |
| 161 | + } |
| 162 | + for ( i = ( x.length/2 ) - 1; i >= index; i-- ) { |
| 163 | + out[ io + ( ( i + 1 ) * so ) ] = out[ io + ( i * so ) ]; |
| 164 | + out[ ( io + ( ( i + 1 ) * so ) ) + 1] = out[ io + ( i * so ) + 1]; |
| 165 | + } |
| 166 | + out[ io + ( index * so ) ] = real( value ); |
| 167 | + out[ io + ( index * so ) + 1] = imag( value ); |
| 168 | + |
| 169 | + return out; |
| 170 | +} |
| 171 | + |
| 172 | + |
| 173 | +// MAIN // |
| 174 | + |
| 175 | +/** |
| 176 | +* Copies elements from one array to another array and inserts the element at the specified index to a provided value. |
| 177 | +* |
| 178 | +* @param {Collection} x - input array |
| 179 | +* @param {integer} index - element index |
| 180 | +* @param {*} value - inserting value |
| 181 | +* @param {Collection} out - output array |
| 182 | +* @param {integer} stride - output array stride |
| 183 | +* @param {NonNegativeInteger} offset - output array offset |
| 184 | +* @throws {RangeError} second argument must not exceed array bounds |
| 185 | +* @returns {Collection} output array |
| 186 | +* |
| 187 | +* @example |
| 188 | +* var x = [ 1, 2, 3, 4 ]; |
| 189 | +* |
| 190 | +* var out = [ 0, 0, 0, 0, 0 ]; |
| 191 | +* var arr = assign( x, 0, 5, out, 1, 0 ); |
| 192 | +* // returns [ 5, 1, 2, 3, 4 ] |
| 193 | +* |
| 194 | +* var bool = ( arr === out ); |
| 195 | +* // returns true |
| 196 | +*/ |
| 197 | +function assign( x, index, value, out, stride, offset ) { |
| 198 | + var xo; |
| 199 | + var oo; |
| 200 | + |
| 201 | + index = normalizeIndex( index, x.length-1 ); |
| 202 | + if ( index < 0 ) { |
| 203 | + throw new RangeError( format( 'invalid argument. Index argument is out-of-bounds. Value: `%d`.', index ) ); |
| 204 | + } |
| 205 | + xo = arraylike2object( x ); |
| 206 | + oo = arraylike2object( out ); |
| 207 | + if ( xo.accessorProtocol || oo.accessorProtocol ) { |
| 208 | + // Note: we only explicitly support a limited set of dtype-to-dtype pairs, as this function should not be concerned with casting rules, etc. That is left to userland... |
| 209 | + if ( |
| 210 | + isComplexDataType( xo.dtype ) && |
| 211 | + isComplexDataType( oo.dtype ) && |
| 212 | + isComplexLike( value ) |
| 213 | + ) { |
| 214 | + complex( reinterpret( x, 0 ), index, value, reinterpret( out, 0 ), stride, offset ); // eslint-disable-line max-len |
| 215 | + return out; |
| 216 | + } |
| 217 | + if ( |
| 218 | + isBooleanDataType( xo.dtype ) && |
| 219 | + isBooleanDataType( oo.dtype ) |
| 220 | + ) { |
| 221 | + indexed( reinterpretBoolean( x, 0 ), index, Boolean( value ), reinterpretBoolean( out, 0 ), stride, offset ); // eslint-disable-line max-len |
| 222 | + return out; |
| 223 | + } |
| 224 | + accessors( xo, index, value, oo, stride, offset ); |
| 225 | + return out; |
| 226 | + } |
| 227 | + indexed( x, index, value, out, stride, offset ); |
| 228 | + return out; |
| 229 | +} |
| 230 | + |
| 231 | + |
| 232 | +// EXPORTS // |
| 233 | + |
| 234 | +module.exports = assign; |
0 commit comments