# include # include # include # include # include "rref2.h" int main ( ); void is_rref_test ( ); void rref_compute_test ( ); void rref_columns_test ( ); void rref_determinant_test ( ); void rref_inverse_test ( ); void rref_rank_test ( ); void rref_solve_test ( ); void i4vec_print ( int n, int a[], char *title ); double *r8mat_mm_new ( int n1, int n2, int n3, double a[], double b[] ); void r8mat_print ( int m, int n, double a[], char *title ); void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ); void timestamp ( ); /******************************************************************************/ int main ( ) /******************************************************************************/ /* Purpose: rref2_test() tests rref2(). Licensing: This code is distributed under the MIT license. Modified: 15 December 2024 Author: John Burkardt */ { timestamp ( ); printf ( "\n" ); printf ( "rref2_test():\n" ); printf ( " C version\n" ); printf ( " Test rref(), which analyzes matrices using the\n" ); printf ( " reduced row echelon form (RREF)\n" ); is_rref_test ( ); rref_compute_test ( ); rref_columns_test ( ); rref_determinant_test ( ); rref_inverse_test ( ); rref_rank_test ( ); rref_solve_test ( ); /* Terminate. */ printf ( "\n" ); printf ( "rref2_test():\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; } /******************************************************************************/ void is_rref_test ( ) /******************************************************************************/ /* Purpose: is_rref_test() tests is_rref(). Licensing: This code is distributed under the MIT license. Modified: 15 December 2024 Author: [ John Burkardt */ { int m = 4; int n = 5; /* Zero rows must come last. */ double A0[4*5] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 9, 0, 0, 1, 4, 8, 0, 0 }; /* First nonzero must be to right of first nonzero in previous row. */ double A1[4*5] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 9, 1, 0, 1, 4, 0, 8, 0 }; /* First nonzero must be a 1. */ double A2[4*5] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 9, 2, 0, 0, 4, 8, 0, 0 }; /* First nonzero must only nonzero in its column. */ double A3[4*5] = { 1, 0, 0, 0, 0, 1, 0, 0, 3, 0, 1, 0, 9, 2, 0, 0, 4, 8, 0, 0 }; /* RREF example. */ double A4[4*5] = { 1, 0, 0, 0, 0, 1, 0, 0, 3, 2, 0, 0, 0, 0, 1, 0, 4, 8, 0, 0 }; printf ( "\n" ); printf ( "is_rref_test():\n" ); printf ( " is_rref() reports if a matrix is in reduced row echelon format.\n" ); r8mat_print ( m, n, A0, " Matrix A0:" ); printf ( " is_rref(A0) = %d\n", is_rref ( m, n, A0 ) ); r8mat_print ( m, n, A1, " Matrix A1:" ); printf ( " is_rref(A1) = %d\n", is_rref ( m, n, A1 ) ); r8mat_print ( m, n, A2, " Matrix A2:" ); printf ( " is_rref(A2) = %d\n", is_rref ( m, n, A2 ) ); r8mat_print ( m, n, A3, " Matrix A3:" ); printf ( " is_rref(A3) = %d\n", is_rref ( m, n, A3 ) ); r8mat_print ( m, n, A4, " Matrix A4:" ); printf ( " is_rref(A4) = %d\n", is_rref ( m, n, A4 ) ); return; } /******************************************************************************/ void rref_columns_test ( ) /******************************************************************************/ /* Purpose: rref_columns_test() tests rref_columns(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[7*4] = { 1, 2, 3, 4, 5, 6, 7, 2, 4, 6, 8, 10, 12, 14, 3, 9, 0, 0, 6, 6, 2, 1, 3, 0, 2, 6, 3, 1 }; int *a_cols; double *A_COLUMNS; double *A_RREF; int i; int j; int j2; int j3; int m = 7; int n = 4; int n2; printf ( "\n" ); printf ( "rref_columns_test():\n" ); printf ( " rref_columns() uses the reduced row echelon form (RREF)\n" ); printf ( " of a matrix to find the linearly independent columns.\n" ); r8mat_print ( m, n, A, " Matrix A:" ); A_RREF = ( double * ) malloc ( m * n * sizeof ( double ) ); a_cols = ( int * ) malloc ( n * sizeof ( int ) ); rref_compute ( m, n, A, A_RREF, a_cols ); n2 = 0; for ( j = 0; j < n; j++ ) { if ( 0 <= a_cols[j] ) { n2 = n2 + 1; } } printf ( "\n" ); printf ( " Number of independent columns is %d\n", n2 ); i4vec_print ( n2, a_cols, " Independent column indices" ); A_COLUMNS = ( double * ) malloc ( m * n2 * sizeof ( double ) ); j2 = 0; for ( j = 0; j < n; j++ ) { if ( a_cols[j] != -1 ) { for ( i = 0; i < m; i++ ) { j3 = a_cols[j]; A_COLUMNS[i+j2*m] = A[i+j3*m]; } j2 = j2 + 1; } } r8mat_print ( m, n2, A_COLUMNS, " Independent columns:" ); free ( A_RREF ); free ( a_cols ); free ( A_COLUMNS ); return; } /******************************************************************************/ void rref_compute_test ( ) /******************************************************************************/ /* Purpose: ref_compute_test() tests rref_compute(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[4*7] = { 1, -2, 3, -1, 3, -6, 9, -3, 0, 0, 0, 0, 2, -2, 0, 1, 6, -8, 6, 0, 3, 3, 6, 9, 1, 1, 2, 3 }; int *a_cols; double *A_RREF; int m = 4; int n = 7; printf ( "\n" ); printf ( "rref_compute_test():\n" ); printf ( " rref_compute() is a user-written code to compute the\n" ); printf ( " reduced row echelon form (RREF) of a matrix.\n" ); r8mat_print ( m, n, A, " Matrix A:" ); A_RREF = ( double * ) malloc ( m * n * sizeof ( double ) ); a_cols = ( int * ) malloc ( n * sizeof ( int ) ); rref_compute ( m, n, A, A_RREF, a_cols ); r8mat_print ( m, n, A_RREF, " rref_compute(A):" ); i4vec_print ( n, a_cols, " Column indices" ); free ( A_RREF ); free ( a_cols ); return; } /******************************************************************************/ void rref_determinant_test ( ) /******************************************************************************/ /* Purpose: rref_determinant_test() tests rref_determinant(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[4*4] = { 5, 7, 6, 5, 7, 10, 8, 7, 6, 8, 10, 9, 5, 7, 9, 10 }; double a_det; int n = 4; printf ( "\n" ); printf ( "rref_determinant_test():\n" ); printf ( " rref_determinant() uses the reduced row echelon form \n" ); printf ( " of a square matrix to compute the determinant.\n" ); r8mat_print ( n, n, A, " matrix A:" ); a_det = rref_determinant ( n, A ); printf ( "\n" ); printf ( " Estimated determinant of A = %g\n", a_det ); return; } /******************************************************************************/ void rref_inverse_test ( ) /******************************************************************************/ /* Purpose: rref_inverse_test() tests rref_inverse(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[4*4] = { 5, 7, 6, 5, 7, 10, 8, 7, 6, 8, 10, 9, 5, 7, 9, 10 }; double *A_INV; int n = 4; double *P; printf ( "\n" ); printf ( "rref_inverse_test():\n" ); printf ( " rref_inverse() uses the reduced row echelon form\n" ); printf ( " of a square matrix to compute its inverse.\n" ); r8mat_print ( n, n, A, " matrix A:" ); A_INV = rref_inverse ( n, A ); r8mat_print ( n, n, A_INV, " Estimated inverse A_inv:" ); P = r8mat_mm_new ( n, n, n, A_INV, A ); r8mat_print ( n, n, P, " Product A_inv * A:" ); free ( A_INV ); free ( P ); return; } /******************************************************************************/ void rref_rank_test ( ) /******************************************************************************/ /* Purpose: rref_rank_test() tests rref_rank(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[4*7] = { 1, -2, 3, -1, 3, -6, 9, -3, 0, 0, 0, 0, 2, -2, 0, 1, 6, -8, 6, 0, 3, 3, 6, 9, 1, 1, 2, 3 }; int a_rank; int m = 4; int n = 7; printf ( "\n" ); printf ( "rref_rank_test():\n" ); printf ( " rref_rank() uses the reduced row echelon form\n" ); printf ( " of a matrix to estimate its rank.\n" ); r8mat_print ( m, n, A, " matrix A:" ); a_rank = rref_rank ( m, n, A ); printf ( "\n" ); printf ( " A has rank %d\n", a_rank ); return; } /******************************************************************************/ void rref_solve_test ( ) /******************************************************************************/ /* Purpose: rref_solve_test() tests rref_solve(). Licensing: This code is distributed under the MIT license. Modified: 08 December 2024 Author: John Burkardt */ { double A[4*4] = { 5, 7, 6, 5, 7, 10, 8, 7, 6, 8, 10, 9, 5, 7, 9, 10 }; double *b; double *b2; int m = 4; int n = 4; int nb = 1; double x[4*1] = { 1, 2, 3, 4 }; double *x2; printf ( "\n" ); printf ( "rref_solve_test():\n" ); printf ( " rref_solve() uses the reduced row echelon form\n" ); printf ( " of a square matrix to solve a linear system.\n" ); r8mat_print ( m, n, A, " matrix A:" ); b = r8mat_mm_new ( m, n, nb, A, x ); r8mat_print ( m, nb, b, " Right hand side b:" ); x2 = rref_solve ( m, n, A, nb, b ); r8mat_print ( n, nb, x2, " Estimated solution:" ); b2 = r8mat_mm_new ( m, n, nb, A, x2 ); r8mat_print ( m, nb, b2, " Product A * x:" ); free ( b ); free ( b2 ); free ( x2 ); return; } /******************************************************************************/ void i4vec_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec_print() prints an I4VEC. Discussion: An I4VEC is a vector of I4"s. Licensing: This code is distributed under the MIT license. Modified: 14 November 2003 Author: John Burkardt Input: int N, the number of components of the vector. int A[N], the vector to be printed. char *TITLE, a title. */ { int i; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); fprintf ( stdout, "\n" ); for ( i = 0; i < n; i++ ) { fprintf ( stdout, " %6d: %8d\n", i, a[i] ); } return; } /******************************************************************************/ double *r8mat_mm_new ( int n1, int n2, int n3, double a[], double b[] ) /******************************************************************************/ /* Purpose: r8mat_mm_new() multiplies two matrices. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. For this routine, the result is returned as the function value. Licensing: This code is distributed under the MIT license. Modified: 08 April 2009 Author: John Burkardt Input: int N1, N2, N3, the order of the matrices. double A[N1*N2], double B[N2*N3], the matrices to multiply. Output: double R8MAT_MM_NEW[N1*N3], the product matrix C = A * B. */ { double *c; int i; int j; int k; c = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( i = 0; i < n1; i++ ) { for ( j = 0; j < n3; j++ ) { c[i+j*n1] = 0.0; for ( k = 0; k < n2; k++ ) { c[i+j*n1] = c[i+j*n1] + a[i+k*n1] * b[k+j*n2]; } } } return c; } /******************************************************************************/ void r8mat_print ( int m, int n, double a[], char *title ) /******************************************************************************/ /* Purpose: r8mat_print() prints an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. Entry A(I,J) is stored as A[I+J*M] Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Input: int M, the number of rows in A. int N, the number of columns in A. double A[M*N], the M by N matrix. char *TITLE, a title. */ { r8mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } /******************************************************************************/ void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ) /******************************************************************************/ /* Purpose: r8mat_print_some() prints some of an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. Licensing: This code is distributed under the MIT license. Modified: 26 June 2013 Author: John Burkardt Input: int M, the number of rows of the matrix. M must be positive. int N, the number of columns of the matrix. N must be positive. double A[M*N], the matrix. int ILO, JLO, IHI, JHI, designate the first row and column, and the last row and column to be printed. char *TITLE, a title. */ { # define INCX 5 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); if ( m <= 0 || n <= 0 ) { fprintf ( stdout, "\n" ); fprintf ( stdout, " (None)\n" ); return; } /* Print the columns of the matrix, in strips of 5. */ for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; if ( n < j2hi ) { j2hi = n; } if ( jhi < j2hi ) { j2hi = jhi; } fprintf ( stdout, "\n" ); /* For each column J in the current range... Write the header. */ fprintf ( stdout, " Col: "); for ( j = j2lo; j <= j2hi; j++ ) { fprintf ( stdout, " %7d ", j - 1 ); } fprintf ( stdout, "\n" ); fprintf ( stdout, " Row\n" ); fprintf ( stdout, "\n" ); /* Determine the range of the rows in this strip. */ if ( 1 < ilo ) { i2lo = ilo; } else { i2lo = 1; } if ( m < ihi ) { i2hi = m; } else { i2hi = ihi; } for ( i = i2lo; i <= i2hi; i++ ) { /* Print out (up to) 5 entries in row I, that lie in the current strip. */ fprintf ( stdout, "%5d:", i - 1 ); for ( j = j2lo; j <= j2hi; j++ ) { fprintf ( stdout, " %14g", a[i-1+(j-1)*m] ); } fprintf ( stdout, "\n" ); } } return; # undef INCX } /******************************************************************************/ void timestamp ( ) /******************************************************************************/ /* Purpose: timestamp() prints the current YMDHMS date as a time stamp. Example: 17 June 2014 09:45:54 AM Licensing: This code is distributed under the MIT license. Modified: 01 May 2021 Author: John Burkardt */ { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct tm *tm; time_t now; now = time ( NULL ); tm = localtime ( &now ); strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm ); printf ( "%s\n", time_buffer ); return; # undef TIME_SIZE }