// // crea una frazione da un double // t_fraction fraction_fromdouble(double d) { int num; int den; if(!fraction_isdecimal(d)) { num = (d > INT_MAX) ? INT_MAX : d; den = 1; } else { int max = 9; int m = 1; while(fraction_isdecimal(d) && max > 0) { --max; m *= 10; d = d * 10.0; } num = (d > INT_MAX) ? INT_MAX : d; den = m; } // crea la frazione t_fraction f = fraction_create(num, den); // riduce ai minimi termini fraction_reduce(&f); return f; };
// // divide la frazione f1 per la frazione f2 // t_fraction fraction_div(t_fraction f1, t_fraction f2) { t_fraction f = fraction_create(f1.numerator * f2.denominator, f1.denominator * f2.numerator); fraction_reduce(&f); return f; }
// // sottrae le frazioni f1 e f2 // t_fraction fraction_sub(t_fraction f1, t_fraction f2) { assert(f1.denominator != 0); assert(f2.denominator != 0); int lcm = fraction_lcm(f1.denominator, f2.denominator); int num = (f1.numerator * lcm / f1.denominator) - (f2.numerator * lcm / f2.denominator); t_fraction f = fraction_create(num, lcm); fraction_reduce(&f); return f; }
// // Crea una frazione da una string // t_fraction fraction_parse(char *s) { char *p; int idx = -1; int num = 1; int den = 1; // cerca il simbolo '/' p = (char *)strchr(s, '/'); // calcola l'indice del simbolo '/' if (p != NULL) idx = p - s; if(idx == -1) { if(fraction_isnumeric(s)) num = atoi(s); } else { char buff[10]; // numeratore strncpy(buff, s, idx); buff[idx] = '\0'; if(fraction_isnumeric(buff)) num = atoi(buff); // denominatore strcpy(buff, s+idx+1); if(fraction_isnumeric(buff)) den = atoi(buff); } t_fraction f = fraction_create(num, den); return f; }
/* * 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); }