int main(int argc, char* argv[]){ static const char *optString = "o:l:f:r:"; int c; char* picture; char* output; double lambda; int factor; while((c = getopt(argc, argv, optString)) != -1){ switch(c){ case 'l': { lambda = atof(optarg); break; } case 'f': { picture = optarg; break; } case 'o': { output = optarg; break; } case 'r': { factor = atoi(optarg); break; } default: { printf("Cannot parse.\n"); } } } PGMInfo pgm_info = parse_pgm(picture,factor); Matrix matrix = build_matrix(lambda, &pgm_info); double results[pgm_info.fHeight * pgm_info.fWidth]; gauss(matrix, &pgm_info); solve_equations(matrix, &pgm_info, results); create_new_picture(results, output, &pgm_info); free_pixels_memory(&pgm_info); return 0; }
/* * solve_equations() * * Solve linear equations or indeterminate equations. * * @matrix: the matrix * @mx: the number of columns of the matrix * @my: the number of rows of the matrix * @unknowns: the next unknown's id * @base_offset_x, @base_offset_y: the offset of the sub matrix to be solved */ exp* solve_equations(fact **matrix, int mx, int my, int unknowns, int base_offset_x, int base_offset_y) { int idx; fact *temp, *ptr_equ, **ptr_matrix, *prepare, *pc; exp *ret, *rpptr, *solve_equ, *retptr, step; matrix += base_offset_y; /* Exchange equations */ for (ptr_matrix = matrix; ptr_matrix < matrix + my; ptr_matrix++) if (fraction_compare(read_matrix(ptr_matrix, base_offset_x, 0), F_ZERO) != 0) { temp = *matrix; *matrix = *ptr_matrix; *ptr_matrix = temp; break; } /* Allocate memory areas for the results */ ret = (exp*) malloc((mx - 1)*sizeof(exp)); if (!ret) return(NULL); /* CAUTION: this step is pretty important, the memory area of the new expression stack must be filled with zero. */ memset(ret, 0, (mx - 1) * sizeof(exp)); /* Nothing to exchange, remove the first column */ if (fraction_compare(read_matrix(matrix, base_offset_x, 0), F_ZERO) == 0) { *ret = expression_create(0, 1); /* Push a new unknown symbol into the expression stack */ if (!push_expression_node_ex(ret, unknowns + 1, fraction_create(1, 1), fraction_plus)) { free_expression_stack(ret, mx - 1); return(NULL); } if (mx > 2) { /* Remove the first column */ solve_equ = solve_equations(matrix, mx - 1, my, unknowns + 2, base_offset_x + 1, 0); if (!solve_equ) { free_expression_stack(ret, mx - 1); return(NULL); } for (rpptr = solve_equ, retptr = ret + 1, idx = 0; idx < mx - 2; idx++, rpptr++, retptr++) if (!expression_memcpy(retptr, *rpptr, false)) { free_expression_stack(ret, mx - 1); return(NULL); } free_expression_stack(solve_equ, mx - 2); } return(ret); } if (my == 1 || mx == 2) { /* Only one unknown, get the result of it */ step = expression_create(matrix_offset(matrix, base_offset_x + mx - 1, 0)->numerator, matrix_offset(matrix, base_offset_x + mx - 1, 0)->denominator); for (rpptr = ret + 1, ptr_equ = matrix_offset(matrix, base_offset_x + 1, 0), pc = matrix_offset(matrix, base_offset_x + mx - 2, 0); ptr_equ <= pc; ptr_equ++, rpptr++) { *rpptr = expression_create(0, 1); /* Generate a new unknown */ /* and then copy values of other unknowns to the result */ if (push_expression_node_ex(rpptr, ++unknowns, fraction_create(1, 1), fraction_plus)) { if (!expression_double_operation(&step, fraction_minus, *rpptr, fraction_multiplination, *ptr_equ)) { free_expression_stack(ret, mx - 1); free_expression(&step); return(NULL); } } else { free_expression_stack(ret, mx - 1); return(NULL); } } expression_division(&step, read_matrix(matrix, base_offset_x, 0)); if (!simplify_expression_node(&step)) { free_expression_stack(ret, mx - 1); free_expression(&step); return(NULL); } *ret = step; } else { /* Have more than one unknown, eliminating */ /* Allocate enough memory areas to contain new equations */ for (ptr_matrix = matrix; ptr_matrix < matrix + my; ptr_matrix++) if (fraction_compare(read_matrix(ptr_matrix, base_offset_x, 0), F_ZERO) != 0) { for (ptr_equ = matrix_offset(ptr_matrix, base_offset_x + mx - 1, 0), pc = matrix_offset(ptr_matrix, base_offset_x, 0); ptr_equ >= pc; ptr_equ--) *ptr_equ = fraction_division(*ptr_equ, read_matrix(ptr_matrix, base_offset_x, 0)); if (ptr_matrix != matrix) for (prepare = matrix_offset(matrix, base_offset_x, 0), ptr_equ = matrix_offset(ptr_matrix, base_offset_x, 0); ptr_equ < matrix_offset(ptr_matrix, base_offset_x + mx, 0); prepare++, ptr_equ++) *ptr_equ = fraction_minus(*ptr_equ, *prepare); } /* Generate the eliminated equations */ solve_equ = solve_equations(matrix, mx - 1, my - 1, unknowns, base_offset_x + 1, 1); if (!solve_equ) { free_expression_stack(ret, mx - 1); return(NULL); } /* Calculate the value of the unknown in the first column */ step = expression_create(matrix_offset(matrix, base_offset_x + mx - 1, 0)->numerator, matrix_offset(matrix, base_offset_x + mx - 1, 0)->denominator); for (rpptr = solve_equ, ptr_equ = matrix_offset(matrix, base_offset_x + 1, 0); ptr_equ <= matrix_offset(matrix, base_offset_x + mx - 2, 0); rpptr++, ptr_equ++) if (!expression_double_operation(&step, fraction_minus, *rpptr, fraction_multiplination, *ptr_equ)) { free_expression_stack(ret, mx - 1); free_expression(&step); return(NULL); } if (!simplify_expression_node(&step)) { free_expression_stack(ret, mx - 1); free_expression(&step); return(NULL); } /* Copy values of other unknowns to the result */ for (*ret = step, rpptr = solve_equ, retptr = ret + 1, idx = 0; idx < mx - 2; idx++, rpptr++, retptr++) if (!expression_memcpy(retptr, *rpptr, false)) { free_expression_stack(ret, mx - 1); return(NULL); } free_expression_stack(solve_equ, mx - 2); } return(ret); }