All files main.js

100% Statements 144/144
100% Branches 21/21
100% Functions 1/1
100% Lines 144/144

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 134 135 136 137 138 139 140 141 142 143 144 1451x 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 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 51x 4x 4x 47x 47x 51x 2x 2x 45x 45x 45x 45x 51x 6x 6x 51x 6x 6x 33x 33x 33x 33x 51x 51x 51x 51x 51x 51x 51x 51x 1x 1x 33x 33x 33x 51x 30x 30x 33x 33x 33x 33x 51x 73x 66x 66x 7x 7x 7x 33x 33x 33x 33x 33x 33x 51x 1x 1x 1x 1x 1x  
/**
* @license Apache-2.0
*
* Copyright (c) 2026 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 toUniqueNormalizedIndices = require( '@stdlib/ndarray/base/to-unique-normalized-indices' );
var getDType = require( '@stdlib/ndarray/base/dtype' );
var getShape = require( '@stdlib/ndarray/base/shape' );
var getStrides = require( '@stdlib/ndarray/base/strides' );
var getOffset = require( '@stdlib/ndarray/base/offset' );
var getOrder = require( '@stdlib/ndarray/base/order' );
var getData = require( '@stdlib/ndarray/base/data-buffer' );
var join = require( '@stdlib/array/base/join' );
var min = require( '@stdlib/math/base/special/min' );
var format = require( '@stdlib/string/format' );
 
 
// MAIN //
 
/**
* Returns a view of the diagonal of a matrix (or stack of matrices).
*
* ## Notes
*
* -   The order of the dimension indices contained in `dims` matters. The first element specifies the row-like dimension. The second element specifies the column-like dimension.
* -   Each provided dimension index must reside on the interval `[-ndims, ndims-1]`.
* -   The diagonal offset `k` is interpreted as `column - row`. Accordingly, when `k = 0`, the function returns the main diagonal; when `k > 0`, the function returns the diagonal above the main diagonal; and when `k < 0`, the function returns the diagonal below the main diagonal.
* -   The returned ndarray is a **view** of the input ndarray. Accordingly, writing to the original ndarray will **mutate** the returned ndarray and vice versa.
* -   The `writable` parameter **only** applies to ndarray constructors supporting **read-only** instances.
*
* @param {ndarray} x - input array
* @param {IntegerArray} dims - dimension indices defining the plane from which to extract the diagonal
* @param {integer} k - diagonal offset
* @param {boolean} writable - boolean indicating whether the returned ndarray should be writable
* @throws {RangeError} must provide exactly two dimension indices
* @throws {RangeError} input ndarray must have at least two dimensions
* @throws {RangeError} must provide valid dimension indices
* @throws {Error} must provide unique dimension indices
* @returns {ndarray} ndarray view
*
* @example
* var array = require( '@stdlib/ndarray/array' );
*
* var x = array( [ [ 1.0, 2.0, 3.0 ], [ 4.0, 5.0, 6.0 ], [ 7.0, 8.0, 9.0 ] ] );
* // returns <ndarray>[ [ 1.0, 2.0, 3.0 ], [ 4.0, 5.0, 6.0 ], [ 7.0, 8.0, 9.0 ] ]
*
* var y = diagonal( x, [ 0, 1 ], 0, false );
* // returns <ndarray>[ 1.0, 5.0, 9.0 ]
*/
function diagonal( x, dims, k, writable ) {
	var strides;
	var offset;
	var ndims;
	var shape;
	var rows;
	var cols;
	var sh;
	var st;
	var sr;
	var sc;
	var ro;
	var co;
	var d;
	var L;
	var i;
 
	if ( dims.length !== 2 ) {
		throw new RangeError( format( 'invalid argument. Must provide exactly two dimension indices. Value: `[%s]`.', join( dims, ', ' ) ) );
	}
	sh = getShape( x );
	ndims = sh.length;
	if ( ndims < 2 ) {
		throw new RangeError( format( 'invalid argument. First argument must be an ndarray having at least two dimensions. Number of dimensions: %d.', ndims ) );
	}
	st = getStrides( x );
 
	// Resolve dimension indices...
	d = toUniqueNormalizedIndices( dims, ndims-1 );
	if ( d === null ) {
		throw new RangeError( format( 'invalid argument. Specified dimension index is out-of-bounds. Must be on the interval: [-%u, %u]. Value: `[%s]`.', ndims, ndims-1, join( dims, ', ' ) ) );
	}
	if ( d.length !== dims.length ) {
		throw new Error( format( 'invalid argument. Must provide unique dimension indices. Value: `[%s]`.', join( dims, ', ' ) ) );
	}
	sr = st[ d[0] ];
	sc = st[ d[1] ];
 
	// Resolve the row and column offsets corresponding to the diagonal offset `k = column - row`:
	co = ( k > 0 ) ? k : 0;
	ro = co - k;
 
	// Compute the length of the diagonal:
	rows = sh[ d[0] ] - ro;
	cols = sh[ d[1] ] - co;
	L = min( rows, cols );
	if ( L < 0 ) {
		L = 0;
	}
 
	// Adjust the offset so that we point to the first element along the specified diagonal:
	offset = getOffset( x );
	if ( L > 0 ) {
		offset += ( co*sc ) + ( ro*sr );
	}
 
	// Drop the specified dimensions and append the diagonal dimension:
	shape = [];
	strides = [];
	for ( i = 0; i < ndims; i++ ) {
		if ( i === d[0] || i === d[1] ) {
			continue;
		}
		shape.push( sh[ i ] );
		strides.push( st[ i ] );
	}
	shape.push( L );
	strides.push( sr + sc );
 
	return new x.constructor( getDType( x ), getData( x ), shape, strides, offset, getOrder( x ), { // eslint-disable-line max-len
		'readonly': !writable
	});
}
 
 
// EXPORTS //
 
module.exports = diagonal;