struct matrix rref (struct matrix M) { // TODO: Fails on matrix with 0s leading first rows /* Algorithm description: Find a row with zero in previous column values and non-zero entry in current column multiply row to change non-zero entry to 1 zero all other row's column entry repeat for each column */ struct matrix R = copy_of_matrix(M); int c,r; int pivot = 1; for(c=1; c<=R.columns && pivot < R.rows; c++) { for(r=pivot; r<=R.rows; r++) { // iterate over column if(get_element(R,r,c).p != 0) { // find non-zero value _multiply_row(R,r_divide(int_to_r(1),get_element(R,r,c)),r); // change pivot to 1 for(int m=1; m<=R.rows; m++) { // zero all other values in that column if (m != r) { _add_multiple(R, r_multiply(int_to_r(-1),get_element(R,m,c)), r,m); } } pivot++; break; } } } _sort_matrix_rows(R); return R; }
void multiply_test() { int p,q,s,t; for ( p = -100; p <= 100; p+=5) { for ( q = -100; q <= 100; q+=5) { for ( s = -100; s <= 100; s+=5) { for ( t = -100; t <= 100; t+=5) { if (q != 0 && t != 0) { struct rational r = new_rational(p,q); struct rational u = new_rational(s,t); struct rational product= r_multiply(r,u); if ((product.p*1.0)/(product.q*1.0) < (p*1.0/q*1.0*s*1.0/t*1.0)-1e-5 || (product.p*1.0)/(product.q*1.0) > (p*1.0/q*1.0*s*1.0/t*1.0)+1e-5) { printf("\nMultiply failed: %d/%d %d/%d\n",p,q,s,t); printf("%.19g %.19g\n",(product.p*1.0)/(product.q*1.0),(p*1.0/q*1.0+s*1.0/t*1.0)); return; } if (r.q ==0) { printf("0 denominator failure\n"); return; } } } if(p%500 == 0){ printf("."); fflush(stdout); } } } } }
struct rational cofactor (struct matrix M, int row, int column){ //TODO: test function if ((row%2) == (column%2)) { return(determinant(submatrix(M,row,column))); } else { return(r_multiply(int_to_r(-1), determinant(submatrix(M,row,column)))); } }
void _multiply_row(struct matrix M, struct rational factor, int row){ set_error(NONE); if(row >0 && row<=M.rows){ int col; for(col=1; col<=M.columns; col++){ set_element(M,row,col,r_multiply(factor,get_element(M,row,col))); } } else set_error(INCOMPATIBLE_MATRIX); }
struct matrix scalar_multiply(struct rational a, struct matrix B){ //a * B struct matrix C = new_matrix(B.rows, B.columns); int i,j; for (i=1; i<=C.rows; i++) { for (j=1; j<=C.columns; j++) { set_element(C, i, j, r_multiply(a, get_element(B,i,j))); } } return C; }
struct rational row_times_column(struct matrix A, int row, struct matrix B, int column){ int i; struct rational sum = new_rational(0,1); //sum A[row][i]*B[j][column] if (A.columns == B.rows){ for (i=1; i<=A.columns; i++) { sum = r_add(sum, r_multiply( get_element(A,row,i), get_element(B,i,column))); } } return sum; }
void _add_multiple(struct matrix M, struct rational factor, int input_row, int modified_row){ set_error(NONE); if(input_row > 0 && modified_row > 0 && input_row <= M.rows && modified_row <= M.rows){ struct rational temp; int col; for(col=1; col<=M.columns; col++){ temp = r_multiply(factor, get_element(M,input_row,col)); temp = r_add(temp, get_element(M,modified_row,col)); set_element(M,modified_row,col,temp); } } else set_error(INCOMPATIBLE_MATRIX); }
struct matrix ref ( struct matrix M) { //TODO: this struct matrix R = copy_of_matrix(M); int c,r; int pivot = 1; for(c=1; c<=R.columns && pivot < R.rows; c++) { _sort_matrix_rows(R); for(r=pivot; r<=R.rows; r++) { // iterate over column if(get_element(R,r,c).p != 0) { // find non-zero value for(int m=1; m<=R.rows; m++) { // zero all other values in that column if (m > r) { _add_multiple(R, r_multiply(get_element(R,r,c),r_reciprocal(get_element(R,m,c))), r,m); } } pivot++; break; } } } _sort_matrix_rows(R); return R; }
rsexp r_divide (RState* r, rsexp lhs, rsexp rhs) { ensure (rhs = r_invert (r, rhs)); return r_multiply (r, lhs, rhs); }