# Coded by Nathan Wallach, May 2019 # based on Davide Cervone's recommendation from # http://webwork.maa.org/moodle/mod/forum/discuss.php?d=3194 # as the current $Matrix->order_LR does not use fuzzy comparisons # so does not give good results. sub rank { # It assumes that a MathObject matrix object is sent my $MM1 = shift; if ( $MM1->class ne "Matrix") { return -1; # Not a matrix } # For the case it is square my $MM = $MM1; my ($Rrows,$Rcols) = $MM1->dimensions; if ( ( $Rrows <= 0 ) || ( $Rcols <= 0 ) ) { return -1; # Not a matrix } if ( $Rrows < $Rcols ) { # pad to make it square my @rows = (); my $i = 1; for ( $i = 1 ; $i <= $Rrows ; $i++ ) { push( @rows, $MM1->row($i) ); } while ( $i <= $Rrows ) { # pad with zero rows push( @rows, ( 0 * $MM1->row(1) ) ); $i++; } $MM = Matrix( @rows ); } elsif ( $Rrows > $Rcols ) { return( rank( $MM1->transpose ) ); } # Davide's approach from http://webwork.maa.org/moodle/mod/forum/discuss.php?d=3194 my $tempR = $MM->R; ($Rrows,$Rcols) = $tempR->dimensions; my $rank; for ( $rank = $Rrows ; $rank >= 1; $rank-- ) { last if ( $tempR->element($rank,$rank) != Real("0") ); } return( $rank ); } 1;