@@ -23,16 +23,16 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
2323 < div class ='clearfix '>
2424
2525 < div class ='fl pad1y space-right2 '>
26- < span class ="strong "> 98.11 % </ span >
26+ < span class ="strong "> 98.61 % </ span >
2727 < span class ="quiet "> Statements</ span >
28- < span class ='fraction '> 104/106 </ span >
28+ < span class ='fraction '> 142/144 </ span >
2929 </ div >
3030
3131
3232 < div class ='fl pad1y space-right2 '>
33- < span class ="strong "> 94.44 % </ span >
33+ < span class ="strong "> 94.73 % </ span >
3434 < span class ="quiet "> Branches</ span >
35- < span class ='fraction '> 17/18 </ span >
35+ < span class ='fraction '> 18/19 </ span >
3636 </ div >
3737
3838
@@ -44,9 +44,9 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
4444
4545
4646 < div class ='fl pad1y space-right2 '>
47- < span class ="strong "> 98.11 % </ span >
47+ < span class ="strong "> 98.61 % </ span >
4848 < span class ="quiet "> Lines</ span >
49- < span class ='fraction '> 104/106 </ span >
49+ < span class ='fraction '> 142/144 </ span >
5050 </ div >
5151
5252
@@ -169,7 +169,45 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
169169< a name ='L104 '> </ a > < a href ='#L104 '> 104</ a >
170170< a name ='L105 '> </ a > < a href ='#L105 '> 105</ a >
171171< a name ='L106 '> </ a > < a href ='#L106 '> 106</ a >
172- < a name ='L107 '> </ a > < a href ='#L107 '> 107</ a > </ td > < td class ="line-coverage quiet "> < span class ="cline-any cline-yes "> 3x</ span >
172+ < a name ='L107 '> </ a > < a href ='#L107 '> 107</ a >
173+ < a name ='L108 '> </ a > < a href ='#L108 '> 108</ a >
174+ < a name ='L109 '> </ a > < a href ='#L109 '> 109</ a >
175+ < a name ='L110 '> </ a > < a href ='#L110 '> 110</ a >
176+ < a name ='L111 '> </ a > < a href ='#L111 '> 111</ a >
177+ < a name ='L112 '> </ a > < a href ='#L112 '> 112</ a >
178+ < a name ='L113 '> </ a > < a href ='#L113 '> 113</ a >
179+ < a name ='L114 '> </ a > < a href ='#L114 '> 114</ a >
180+ < a name ='L115 '> </ a > < a href ='#L115 '> 115</ a >
181+ < a name ='L116 '> </ a > < a href ='#L116 '> 116</ a >
182+ < a name ='L117 '> </ a > < a href ='#L117 '> 117</ a >
183+ < a name ='L118 '> </ a > < a href ='#L118 '> 118</ a >
184+ < a name ='L119 '> </ a > < a href ='#L119 '> 119</ a >
185+ < a name ='L120 '> </ a > < a href ='#L120 '> 120</ a >
186+ < a name ='L121 '> </ a > < a href ='#L121 '> 121</ a >
187+ < a name ='L122 '> </ a > < a href ='#L122 '> 122</ a >
188+ < a name ='L123 '> </ a > < a href ='#L123 '> 123</ a >
189+ < a name ='L124 '> </ a > < a href ='#L124 '> 124</ a >
190+ < a name ='L125 '> </ a > < a href ='#L125 '> 125</ a >
191+ < a name ='L126 '> </ a > < a href ='#L126 '> 126</ a >
192+ < a name ='L127 '> </ a > < a href ='#L127 '> 127</ a >
193+ < a name ='L128 '> </ a > < a href ='#L128 '> 128</ a >
194+ < a name ='L129 '> </ a > < a href ='#L129 '> 129</ a >
195+ < a name ='L130 '> </ a > < a href ='#L130 '> 130</ a >
196+ < a name ='L131 '> </ a > < a href ='#L131 '> 131</ a >
197+ < a name ='L132 '> </ a > < a href ='#L132 '> 132</ a >
198+ < a name ='L133 '> </ a > < a href ='#L133 '> 133</ a >
199+ < a name ='L134 '> </ a > < a href ='#L134 '> 134</ a >
200+ < a name ='L135 '> </ a > < a href ='#L135 '> 135</ a >
201+ < a name ='L136 '> </ a > < a href ='#L136 '> 136</ a >
202+ < a name ='L137 '> </ a > < a href ='#L137 '> 137</ a >
203+ < a name ='L138 '> </ a > < a href ='#L138 '> 138</ a >
204+ < a name ='L139 '> </ a > < a href ='#L139 '> 139</ a >
205+ < a name ='L140 '> </ a > < a href ='#L140 '> 140</ a >
206+ < a name ='L141 '> </ a > < a href ='#L141 '> 141</ a >
207+ < a name ='L142 '> </ a > < a href ='#L142 '> 142</ a >
208+ < a name ='L143 '> </ a > < a href ='#L143 '> 143</ a >
209+ < a name ='L144 '> </ a > < a href ='#L144 '> 144</ a >
210+ < a name ='L145 '> </ a > < a href ='#L145 '> 145</ a > </ td > < td class ="line-coverage quiet "> < span class ="cline-any cline-yes "> 3x</ span >
173211< span class ="cline-any cline-yes "> 3x</ span >
174212< span class ="cline-any cline-yes "> 3x</ span >
175213< span class ="cline-any cline-yes "> 3x</ span >
@@ -217,6 +255,22 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
217255< span class ="cline-any cline-yes "> 3x</ span >
218256< span class ="cline-any cline-yes "> 3x</ span >
219257< span class ="cline-any cline-yes "> 3x</ span >
258+ < span class ="cline-any cline-yes "> 3x</ span >
259+ < span class ="cline-any cline-yes "> 3x</ span >
260+ < span class ="cline-any cline-yes "> 3x</ span >
261+ < span class ="cline-any cline-yes "> 3x</ span >
262+ < span class ="cline-any cline-yes "> 3x</ span >
263+ < span class ="cline-any cline-yes "> 3x</ span >
264+ < span class ="cline-any cline-yes "> 3x</ span >
265+ < span class ="cline-any cline-yes "> 3x</ span >
266+ < span class ="cline-any cline-yes "> 3x</ span >
267+ < span class ="cline-any cline-yes "> 3x</ span >
268+ < span class ="cline-any cline-yes "> 3x</ span >
269+ < span class ="cline-any cline-yes "> 26x</ span >
270+ < span class ="cline-any cline-yes "> 26x</ span >
271+ < span class ="cline-any cline-yes "> 26x</ span >
272+ < span class ="cline-any cline-yes "> 26x</ span >
273+ < span class ="cline-any cline-yes "> 26x</ span >
220274< span class ="cline-any cline-yes "> 26x</ span >
221275< span class ="cline-any cline-yes "> 26x</ span >
222276< span class ="cline-any cline-yes "> 26x</ span >
@@ -232,26 +286,45 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
232286< span class ="cline-any cline-yes "> 24x</ span >
233287< span class ="cline-any cline-yes "> 24x</ span >
234288< span class ="cline-any cline-yes "> 24x</ span >
289+ < span class ="cline-any cline-yes "> 24x</ span >
290+ < span class ="cline-any cline-yes "> 24x</ span >
235291< span class ="cline-any cline-yes "> 26x</ span >
236292< span class ="cline-any cline-no "> </ span >
237293< span class ="cline-any cline-no "> </ span >
238294< span class ="cline-any cline-yes "> 24x</ span >
239295< span class ="cline-any cline-yes "> 26x</ span >
240296< span class ="cline-any cline-yes "> 12x</ span >
241297< span class ="cline-any cline-yes "> 12x</ span >
242- < span class ="cline-any cline-yes "> 30x</ span >
298+ < span class ="cline-any cline-yes "> 12x</ span >
299+ < span class ="cline-any cline-yes "> 12x</ span >
300+ < span class ="cline-any cline-yes "> 12x</ span >
301+ < span class ="cline-any cline-yes "> 12x</ span >
302+ < span class ="cline-any cline-yes "> 12x</ span >
303+ < span class ="cline-any cline-yes "> 12x</ span >
304+ < span class ="cline-any cline-yes "> 12x</ span >
305+ < span class ="cline-any cline-yes "> 12x</ span >
243306< span class ="cline-any cline-yes "> 30x</ span >
244307< span class ="cline-any cline-yes "> 54x</ span >
245308< span class ="cline-any cline-yes "> 6x</ span >
246309< span class ="cline-any cline-yes "> 6x</ span >
310+ < span class ="cline-any cline-yes "> 6x</ span >
247311< span class ="cline-any cline-yes "> 48x</ span >
248312< span class ="cline-any cline-yes "> 48x</ span >
249313< span class ="cline-any cline-yes "> 24x</ span >
250314< span class ="cline-any cline-yes "> 24x</ span >
251315< span class ="cline-any cline-yes "> 6x</ span >
252316< span class ="cline-any cline-yes "> 6x</ span >
253317< span class ="cline-any cline-yes "> 6x</ span >
254- < span class ="cline-any cline-yes "> 6x</ span >
318+ < span class ="cline-any cline-yes "> 12x</ span >
319+ < span class ="cline-any cline-yes "> 12x</ span >
320+ < span class ="cline-any cline-yes "> 12x</ span >
321+ < span class ="cline-any cline-yes "> 12x</ span >
322+ < span class ="cline-any cline-yes "> 12x</ span >
323+ < span class ="cline-any cline-yes "> 12x</ span >
324+ < span class ="cline-any cline-yes "> 12x</ span >
325+ < span class ="cline-any cline-yes "> 12x</ span >
326+ < span class ="cline-any cline-yes "> 12x</ span >
327+ < span class ="cline-any cline-yes "> 12x</ span >
255328< span class ="cline-any cline-yes "> 12x</ span >
256329< span class ="cline-any cline-yes "> 12x</ span >
257330< span class ="cline-any cline-yes "> 12x</ span >
@@ -261,14 +334,17 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
261334< span class ="cline-any cline-yes "> 24x</ span >
262335< span class ="cline-any cline-yes "> 24x</ span >
263336< span class ="cline-any cline-yes "> 24x</ span >
264- < span class ="cline-any cline-yes "> 48x</ span >
265- < span class ="cline-any cline-yes "> 48x</ span >
266- < span class ="cline-any cline-yes "> 48x</ span >
267337< span class ="cline-any cline-yes "> 24x</ span >
268338< span class ="cline-any cline-yes "> 24x</ span >
339+ < span class ="cline-any cline-yes "> 54x</ span >
340+ < span class ="cline-any cline-yes "> 6x</ span >
341+ < span class ="cline-any cline-yes "> 6x</ span >
342+ < span class ="cline-any cline-yes "> 6x</ span >
343+ < span class ="cline-any cline-yes "> 6x</ span >
344+ < span class ="cline-any cline-yes "> 48x</ span >
345+ < span class ="cline-any cline-yes "> 48x</ span >
269346< span class ="cline-any cline-yes "> 24x</ span >
270347< span class ="cline-any cline-yes "> 12x</ span >
271- < span class ="cline-any cline-yes "> 12x</ span >
272348< span class ="cline-any cline-yes "> 26x</ span >
273349< span class ="cline-any cline-yes "> 3x</ span >
274350< span class ="cline-any cline-yes "> 3x</ span >
@@ -298,14 +374,17 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
298374// MODULES //
299375
300376var isRowMajor = require( '@stdlib/ndarray/base/assert/is-row-major' );
301- var max = require( '@stdlib/math/base/special/max' );
302377
303378
304379// MAIN //
305380
306381/**
307382* Finds the index of the last non-zero row in a matrix `A`.
308383*
384+ * ## Notes
385+ *
386+ * - If provided an empty matrix or a matrix containing only zeros, the function returns `-1` (i.e., an invalid index).
387+ *
309388* @private
310389* @param {PositiveInteger} M - number of rows in `A`
311390* @param {PositiveInteger} N - number of columns in `A`
@@ -322,59 +401,94 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
322401*
323402* var out = iladlr( 3, 2, A, 2, 1, 0 );
324403* // returns 1
404+ *
405+ * @example
406+ * var Float64array = require( '@stdlib/array/float64' );
407+ *
408+ * var A = new Float64array( [ 1.0, 3.0, 0.0, 2.0, 4.0, 0.0 ] ); // => [ [ 1.0, 2.0 ], [ 3.0, 4.0 ], [ 0.0, 0.0 ] ]
409+ *
410+ * var out = iladlr( 3, 2, A, 1, 3, 0 );
411+ * // returns 1
325412*/
326413function iladlr( M, N, A, strideA1, strideA2, offsetA ) {
327- var iladlr;
328- var ia1;
329- var ia2;
330- var i;
331- var j;
414+ var last;
415+ var da0;
416+ var da1;
417+ var S0;
418+ var S1;
419+ var ia;
420+ var i0;
421+ var i1;
422+ var k;
332423
333- if ( M === 0 || N === 0 ) {
334- return -1; // Invalid index
424+ // Check whether the matrix is an empty matrix...
425+ if ( M <= 0 || N <= 0 ) {
426+ return -1;
335427 }
428+ // Compute the index of the first element in the last row:
429+ ia = offsetA + ( (M-1) * strideA1 );
336430
337- ia1 = offsetA + ( (M-1) * strideA1 ); // A( M, 1 )
338- ia2 = ia1 + ( ( N-1) * strideA2 ); // A( M, N )
431+ // Compute the index offset for the last element in the last row:
432+ last = ( N-1 ) * strideA2;
339433
340- // Quick test for common case where corners are non-zero:
341- if ( A[ ia1 ] !== 0.0 || A[ ia2 ] !== 0.0 ) < span class ="branch-0 cbranch-no " title ="branch not covered " > {</ span >
434+ // Check for the common case where the first and last elements in the last row are non-zero...
435+ if ( A[ ia ] !== 0.0 || A[ ia+last ] !== 0.0 ) < span class ="branch-0 cbranch-no " title ="branch not covered " > {</ span >
342436< span class ="cstat-no " title ="statement not covered " > return M - 1;</ span >
343437< span class ="cstat-no " title ="statement not covered " > }</ span >
344-
438+ // Search for the last row containing at least one non-zero element...
345439 if ( isRowMajor( [ strideA1, strideA2 ] ) ) {
346- ia1 = offsetA + ( (M-1) * strideA1 ); // Tracks rows
347- for ( i = M - 1; i >= 0; i-- ) {
348- ia2 = 0; // Tracks columns
349- for ( j = 0; j < N; j++ ) {
350- if ( A[ ia1 + ia2 ] !== 0.0 ) { // Find the last row with a non-zero entry
351- return i;
440+ S0 = N;
441+ S1 = M;
442+
443+ // Resolve loop offset (pointer) increments:
444+ da0 = strideA2;
445+ da1 = strideA1 - ( S0*strideA2 );
446+
447+ // Scan a row-major linear buffer from the last indexed element to the first indexed element, always moving in the same direction when both strides are the same sign, thus ensuring cache optimal traversal...
448+ ia += last;
449+ for ( i1 = S1-1; i1 >= 0; i1-- ) {
450+ for ( i0 = 0; i0 < S0; i0++ ) {
451+ if ( A[ ia ] !== 0.0 ) {
452+ // We found a row with a non-zero element!
453+ return i1;
352454 }
353- ia2 += strideA2 ;
455+ ia -= da0 ;
354456 }
355- ia1 -= strideA1 ;
457+ ia -= da1 ;
356458 }
357-
358- // If we reach here, then all entries in the matrix are zero, return -1 (invalid index)
459+ // If we've made it here, then all entries in the matrix are zero:
359460 return -1;
360461 }
462+ // Column-major...
463+ S0 = M;
464+ S1 = N;
465+
466+ // Resolve loop offset (pointer) increments:
467+ da0 = strideA1;
468+ da1 = strideA2;
361469
362- // Column major
363- ia2 = offsetA; // Tracks columns
364- iladlr = -1; // initialize iladlr, will return -1 (invalid index) if all entries are zero
470+ // Compute the index offset for the last element in each row:
471+ last = offsetA + ( (S0-1)*da0 );
365472
366- for ( j = 0; j < N; j++ ) {
367- i = M - 1;
368- ia1 = (M-1) * strideA1; // Tracks rows
369- while ( A[ ia1 + ia2 ] === 0.0 && i >= 0 ) {
370- i -= 1;
371- ia1 -= strideA1;
473+ // Initialize an index of the last row in which a non-zero element was seen:
474+ k = -1;
475+
476+ // Finding the last non-zero row when a matrix is stored in column-major order requires effectively performing a full linear scan. In order to ensure cache-efficient traversal, scan up each column (otherwise, if we went row-by-row, we'd hop around linear memory, resulting in poor cache behavior)...
477+ for ( i1 = 0; i1 < S1; i1++ ) {
478+ // Reset the pointer to point to the last element in the current column:
479+ ia = last + ( i1*da1 );
480+
481+ // Scan up the rows in a column looking for a non-zero element...
482+ for ( i0 = S0-1; i0 > k; i0-- ) { // note: `k` serves as a lower row index bound, thus shrinking the number of rows we need to check when scanning columns
483+ if ( A[ ia ] !== 0.0 ) {
484+ // We found a non-zero element, which means we no longer have to search this row...
485+ k = i0;
486+ break; // note: in principle, if `k == M-1`, we could early return; however, this is a hot loop and adding an additional conditional is likely to degrade average performance in order to cater to what is effectively an edge case
487+ }
488+ ia -= da0;
372489 }
373- iladlr = max( i, iladlr );
374- ia2 += strideA2;
375490 }
376-
377- return iladlr;
491+ return k;
378492}
379493
380494
@@ -388,7 +502,7 @@ <h1><a href="../../../../index.html">All files</a> / <a href="index.html">lapack
388502 < div class ='footer quiet pad2 space-top1 center small '>
389503 Code coverage generated by
390504 < a href ="https://istanbul.js.org/ " target ="_blank " rel ="noopener noreferrer "> istanbul</ a >
391- at 2025-06-04T20:05:39.645Z
505+ at 2025-06-05T07:49:20.832Z
392506 </ div >
393507 < script src ="../../../../prettify.js "> </ script >
394508 < script >
0 commit comments