package mikera.matrixx.algo; import mikera.matrixx.AMatrix; import mikera.matrixx.decompose.ISVDResult; import mikera.matrixx.decompose.SVD; import mikera.vectorz.AVector; public class Rank { private static double DEFAULT_THRESHOLD = 2.220446e-15; /** * Returns the rank of a matrix. * * @param A The input matrix * @return The matrix's rank */ public static int compute(AMatrix A) { return compute(A, DEFAULT_THRESHOLD); } /** * Returns the rank of a matrix. * * @param A The input matrix * @param threshold Tolerance used to determine if a singular value is singular. * @return The matrix's rank */ public static int compute(AMatrix A, double threshold) { ISVDResult ans = SVD.decompose(A, true); int rank = 0; AVector singularValues = ans.getSingularValues(); int n=singularValues.length(); for(int i=0; i<n; i++) { if( singularValues.unsafeGet(i) >= threshold) rank++; } return rank; } /** * Directly computes rank of matrix whose SVD decomposition has already been computed. * * @param result The result of an SVD decomposition * @return The matrix's rank */ public static int compute(ISVDResult result) { return compute(result, DEFAULT_THRESHOLD); } /** * Directly computes rank of matrix whose SVD decomposition has already been computed. * * @param result The result of an SVD decomposition * @param threshold Tolerance used to determine if a singular value is singular. * @return The matrix's rank */ public static int compute(ISVDResult result, double threshold) { int rank = 0; AVector singularValues = result.getSingularValues(); for( double s : singularValues ) { if( s > threshold) rank++; } return rank; } }