add logic for pure quadratics

This commit is contained in:
hugogogo
2026-05-14 23:11:37 +02:00
parent 840f5bcfdf
commit 6c6accc289
7 changed files with 301 additions and 51 deletions

View File

@@ -2,12 +2,98 @@
#include "computorv1.h"
/**
* DEGREE 1
*/
static void print_solution_degree_1(s_solution_degree_1 solution)
{
ft_printf("The solution is:\n");
printf("%g\n", solution.solution);
}
/**
* DEGREE 2 PURE
*/
static void print_solution_pure_radicand_zero()
{
ft_printf("Radicant is equal to zero, the solution is:\n");
printf("0\n");
}
static void print_solution_pure_radicand_positiv(s_solution_degree_2_pure solution)
{
double numerator;
double denominator;
ft_printf("Radicant is strictly positive, the two solutions are:\n");
if (solution.numerator_sqrt_is_int && solution.denominator_sqrt_is_int)
{
numerator = solution.numerator_sqrt;
denominator = solution.denominator_sqrt;
reduce_fraction(&numerator, &denominator);
printf("%g/%g\n", numerator, denominator);
printf("-%g/%g\n", numerator, denominator);
}
else if (solution.numerator_sqrt_is_int)
{
printf("%g/√(%g)\n", solution.numerator_sqrt, solution.c);
printf("-%g/√(%g)\n", solution.numerator_sqrt, solution.c);
}
else if (solution.denominator_sqrt_is_int)
{
printf("√(%g)/%g\n", solution.a, solution.denominator_sqrt);
printf("-√(%g)/%g\n", solution.a, solution.denominator_sqrt);
}
else
{
numerator = solution.numerator_sqrt;
denominator = solution.denominator_sqrt;
reduce_fraction(&numerator, &denominator);
printf("√(%g/%g)\n", numerator, denominator);
printf("-√(%g/%g)\n", numerator, denominator);
}
}
static void print_solution_pure_radicand_negativ(s_solution_degree_2_pure solution)
{
double numerator;
double denominator;
ft_printf("Radicant is strictly negative, the two complex solutions are:\n");
if (solution.numerator_sqrt_is_int && solution.denominator_sqrt_is_int)
{
numerator = solution.numerator_sqrt;
denominator = solution.denominator_sqrt;
reduce_fraction(&numerator, &denominator);
printf("i%g/%g\n", numerator, denominator);
printf("-i%g/%g\n", numerator, denominator);
}
else if (solution.numerator_sqrt_is_int)
{
printf("i%g/√(%g)\n", solution.numerator_sqrt, solution.c);
printf("-i%g/√(%g)\n", solution.numerator_sqrt, solution.c);
}
else if (solution.denominator_sqrt_is_int)
{
printf("i√(%g)/%g\n", solution.a, solution.denominator_sqrt);
printf("-i√(%g)/%g\n", solution.a, solution.denominator_sqrt);
}
else
{
numerator = solution.a;
denominator = solution.c;
reduce_fraction(&numerator, &denominator);
printf("i√(%g/%g)\n", numerator, denominator);
printf("-i√(%g/%g)\n", numerator, denominator);
}
}
/**
* DEGREE 2
*/
static void print_solution_delta_zero(s_solution_degree_2 solution)
{
ft_printf("Discriminant is equal to zero, the solution is:\n");
@@ -59,7 +145,9 @@ static void print_solution_delta_negativ(s_solution_degree_2 solution)
void print_solution(s_solution *solution)
{
s_solution_degree_2 solution_d2;
s_solution_degree_2_pure solution_d2_pure;
e_delta_sign delta_sign;
e_radicand_sign radicand_sign;
// degree 1
@@ -67,7 +155,20 @@ void print_solution(s_solution *solution)
{
return print_solution_degree_1(solution->solution_degree_1);
}
else if (solution->degree == 2)
else if (solution->degree == 2 && solution->is_quadratic_pure)
{
solution_d2_pure = solution->solution_degree_2_pure;
radicand_sign = solution_d2_pure.radicand_sign;
if (radicand_sign == RADICAND_ZERO)
print_solution_pure_radicand_zero();
else if (radicand_sign == RADICAND_PLUS)
print_solution_pure_radicand_positiv(solution_d2_pure);
else if (radicand_sign == RADICAND_MINUS)
print_solution_pure_radicand_negativ(solution_d2_pure);
else
stop_errors("radicand sign is wrong : '%i' , radicand : '%g'", solution_d2_pure.radicand_sign, solution_d2_pure.radicand);
}
else if (solution->degree == 2 && !solution->is_quadratic_pure)
{
solution_d2 = solution->solution_degree_2;
delta_sign = solution_d2.delta_sign;

View File

@@ -32,36 +32,6 @@ static double positiv_zero(double num)
return num;
}
static int has_decimal_part(double num)
{
return (num != (int)num);
}
static bool any_has_decimal_part(double *num, size_t len)
{
while (len > 0)
{
if (has_decimal_part(num[len - 1]))
return true;
len--;
}
return false;
}
// find GCD of two integers using euclidean algorithm
static int gcd_int(int a, int b)
{
int tmp;
while (b != 0)
{
tmp = b;
b = a % b;
a = tmp;
}
return abs(a);
}
static void solve_degree_1(s_solution_degree_1 *solution, double a, double b)
{
solution->a = a;
@@ -120,6 +90,28 @@ static void solve_degree_2(s_solution_degree_2 *solution, double a, double b, do
solution->left_term_denominator = (a * 2) / gcd;
}
static void solve_degree_2_pure(s_solution_degree_2_pure *solution, double a, double c)
{
double radicand;
solution->a = a;
solution->c = c;
radicand = -c / a;
solution->radicand_sign = ft_fsign(radicand); // RADICAND_PLUS or RADICAND_MINUS or RADICAND_ZERO
solution->radicand_absolute = ft_fabs(radicand); // |radicand|
solution->radicand_sqrt = ft_sqrt(solution->radicand_absolute, DOUBLE_PRECISION); // √|radicand|
/**
* SQARE ROOTS
*/
solution->numerator_sqrt = ft_sqrt(a, DOUBLE_PRECISION);
solution->numerator_sqrt_is_int = !has_decimal_part(solution->numerator_sqrt);
solution->denominator_sqrt = ft_sqrt(c, DOUBLE_PRECISION);
solution->denominator_sqrt_is_int = !has_decimal_part(solution->denominator_sqrt);
}
void solve(const s_polynom *polynom, s_solution *solution)
{
double power2;
@@ -138,7 +130,8 @@ void solve(const s_polynom *polynom, s_solution *solution)
{
if (is_nearly_equal_zero(power1))
{
// solve_degree_2_pure(&solution->solution_degree_2, power2, power0);
solution->is_quadratic_pure = true;
solve_degree_2_pure(&solution->solution_degree_2_pure, power2, power0);
}
else
solve_degree_2(&solution->solution_degree_2, power2, power1, power0);

View File

@@ -73,6 +73,7 @@ static void print_context_solution()
{
s_solution_degree_1 solution_d1;
s_solution_degree_2 solution_d2;
s_solution_degree_2_pure solution_d2_pure;
if (solution_g_err->degree == 1)
{
@@ -85,28 +86,51 @@ static void print_context_solution()
}
else if (solution_g_err->degree == 2)
{
solution_d2 = solution_g_err->solution_degree_2;
dprintf(STDERR_FILENO, "degree 2 : delta > 0 ( -b / 2a +- √Δ / 2a )\n");
dprintf(STDERR_FILENO, " delta == 0 ( -b / 2a )\n");
dprintf(STDERR_FILENO, " delta < 0 ( -b / 2a +- i√|Δ| / 2a )\n");
if (solution_g_err->is_quadratic_pure)
{
solution_d2_pure = solution_g_err->solution_degree_2_pure;
dprintf(STDERR_FILENO, "degree 2 pure : radicand > 0 ( +-( -c / 2a ) )\n");
dprintf(STDERR_FILENO, " radicand == 0 ( 0 )\n");
dprintf(STDERR_FILENO, " radicand < 0 ( +-i( -c / 2a ) )\n");
dprintf(STDERR_FILENO, "a : %15g ( a )\n", solution_d2.a);
dprintf(STDERR_FILENO, "b : %15g ( b )\n", solution_d2.b);
dprintf(STDERR_FILENO, "c : %15g ( c )\n", solution_d2.c);
dprintf(STDERR_FILENO, "a : %15g ( a )\n", solution_d2_pure.a);
dprintf(STDERR_FILENO, "c : %15g ( c )\n", solution_d2_pure.c);
dprintf(STDERR_FILENO, "delta : %15g ( Δ == b² - 4ac )\n", solution_d2.delta);
dprintf(STDERR_FILENO, "delta_sign : %15s ( '-' || '+' || '0' )\n", delta_sign_to_str(solution_d2.delta_sign));
dprintf(STDERR_FILENO, "delta_absolute : %15g ( |Δ| )\n", solution_d2.delta_absolute);
dprintf(STDERR_FILENO, "delta_sqrt : %15g ( √|Δ| )\n", solution_d2.delta_sqrt);
dprintf(STDERR_FILENO, "radicand : %15g ( r == x² == -c / a )\n", solution_d2_pure.radicand);
dprintf(STDERR_FILENO, "radicand_sign : %15s ( '-' || '+' || '0' )\n", radicand_sign_to_str(solution_d2_pure.radicand_sign));
dprintf(STDERR_FILENO, "radicand_absolute : %15g ( |r| )\n", solution_d2_pure.radicand_absolute);
dprintf(STDERR_FILENO, "radicand_sqrt : %15g ( √|r| )\n", solution_d2_pure.radicand_sqrt);
dprintf(STDERR_FILENO, "left_term : %15g ( -b / 2a )\n", solution_d2.left_term);
dprintf(STDERR_FILENO, "right_term : %15g ( √|Δ| / 2a )\n", solution_d2.right_term);
dprintf(STDERR_FILENO, "numerator_sqrt : %15g ( √a )\n", solution_d2_pure.numerator_sqrt);
dprintf(STDERR_FILENO, "numerator_sqrt_is_int : %15i ( false if √a is double )\n", solution_d2_pure.numerator_sqrt_is_int);
dprintf(STDERR_FILENO, "denominator_sqrt : %15g ( √c )\n", solution_d2_pure.denominator_sqrt);
dprintf(STDERR_FILENO, "denominator_sqrt_is_int: %15i ( false if √c is double )\n", solution_d2_pure.denominator_sqrt_is_int);
}
else
{
solution_d2 = solution_g_err->solution_degree_2;
dprintf(STDERR_FILENO, "degree 2 : delta > 0 ( -b / 2a +- √Δ / 2a )\n");
dprintf(STDERR_FILENO, " delta == 0 ( -b / 2a )\n");
dprintf(STDERR_FILENO, " delta < 0 ( -b / 2a +- i√|Δ| / 2a )\n");
dprintf(STDERR_FILENO, "all_int : %15i ( are int : b, a, √|Δ| )\n", solution_d2.all_int);
dprintf(STDERR_FILENO, "left_term_numerator : %15i ( -b / left_gcd )\n", solution_d2.left_term_numerator);
dprintf(STDERR_FILENO, "left_term_denominator : %15i ( 2a / left_gcd )\n", solution_d2.left_term_denominator);
dprintf(STDERR_FILENO, "right_term_numerator : %15i ( √|Δ| / right_gcd )\n", solution_d2.right_term_numerator);
dprintf(STDERR_FILENO, "right_term_denominator : %15i ( 2a / right_gcd )\n", solution_d2.right_term_denominator);
dprintf(STDERR_FILENO, "a : %15g ( a )\n", solution_d2.a);
dprintf(STDERR_FILENO, "b : %15g ( b )\n", solution_d2.b);
dprintf(STDERR_FILENO, "c : %15g ( c )\n", solution_d2.c);
dprintf(STDERR_FILENO, "delta : %15g ( Δ == b² - 4ac )\n", solution_d2.delta);
dprintf(STDERR_FILENO, "delta_sign : %15s ( '-' || '+' || '0' )\n", delta_sign_to_str(solution_d2.delta_sign));
dprintf(STDERR_FILENO, "delta_absolute : %15g ( |Δ| )\n", solution_d2.delta_absolute);
dprintf(STDERR_FILENO, "delta_sqrt : %15g ( √|Δ| )\n", solution_d2.delta_sqrt);
dprintf(STDERR_FILENO, "left_term : %15g ( -b / 2a )\n", solution_d2.left_term);
dprintf(STDERR_FILENO, "right_term : %15g ( √|Δ| / 2a )\n", solution_d2.right_term);
dprintf(STDERR_FILENO, "all_int : %15i ( are int : b, a, √|Δ| )\n", solution_d2.all_int);
dprintf(STDERR_FILENO, "left_term_numerator : %15i ( -b / left_gcd )\n", solution_d2.left_term_numerator);
dprintf(STDERR_FILENO, "left_term_denominator : %15i ( 2a / left_gcd )\n", solution_d2.left_term_denominator);
dprintf(STDERR_FILENO, "right_term_numerator : %15i ( √|Δ| / right_gcd )\n", solution_d2.right_term_numerator);
dprintf(STDERR_FILENO, "right_term_denominator : %15i ( 2a / right_gcd )\n", solution_d2.right_term_denominator);
}
}
ft_putchar_fd('\n', STDERR_FILENO);

View File

@@ -10,3 +10,48 @@ bool is_nearly_equal_zero(double num)
return false;
return true;
}
bool has_decimal_part(double num)
{
return (num != (int)num);
}
bool any_has_decimal_part(double *num, size_t len)
{
while (len > 0)
{
if (has_decimal_part(num[len - 1]))
return true;
len--;
}
return false;
}
// find GCD of two integers using euclidean algorithm
int gcd_int(int a, int b)
{
int tmp;
while (b != 0)
{
tmp = b;
b = a % b;
a = tmp;
}
return abs(a);
}
// returns the gcd, and modify arguments with new reduced values
int reduce_fraction(double *numerator, double *denominator)
{
int gcd;
if (any_has_decimal_part((double[]){*numerator, *denominator}, 2))
return 0;
gcd = gcd_int((int)*numerator, (int)*denominator);
*numerator /= gcd;
*denominator /= gcd;
return gcd;
}

View File

@@ -78,4 +78,16 @@ const char *delta_sign_to_str(e_delta_sign enum_value)
return "DELTA_ZERO";
else
return "invalid enum value";
}
const char *radicand_sign_to_str(e_radicand_sign enum_value)
{
if (enum_value == RADICAND_PLUS)
return "RADICAND_PLUS";
else if (enum_value == RADICAND_MINUS)
return "RADICAND_MINUS";
else if (enum_value == RADICAND_ZERO)
return "RADICAND_ZERO";
else
return "invalid enum value";
}