init solver

This commit is contained in:
hugogogo
2026-05-06 22:26:58 +02:00
parent 16c57c9bea
commit 4c13d21e1f
11 changed files with 159 additions and 75 deletions

View File

@@ -42,6 +42,7 @@ SRCS = main.c \
lexer.c \
parser.c \
reducer.c \
solver.c \
errors.c \
printer.c \
print_enums.c
@@ -98,23 +99,23 @@ $(NAME): $(OBJS)
$(CC) $(OBJS) -o $@ $(LFLAGS)
run: $(NAME)
@echo $(B_PURPLE)"\n---------------------------------------------\n2. run without flag \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run without flag \n"$(RESET)
-./$(NAME) "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1"
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with flag '-d' as last \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n2. run with flag '-d' as last \n"$(RESET)
-./$(NAME) "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5 * x^1" -d
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with flag '-d' as first \n"$(RESET)
-./$(NAME) -d "3 * x^2 + 2 * x^2 = 5 * x^1"
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with wrong flag '-e' SHOULD FAIL \n"$(RESET)
-./$(NAME) -d -e "3 * x^2 + 2 * x - 7 * x^4 = 1 * x^4"
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with free form \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n5. run with free form \n"$(RESET)
-./$(NAME) -d "3*x^2 + 2x = 0"
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with float coefficient \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n6. run with float coefficient \n"$(RESET)
-./$(NAME) -d "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5.123 * x^1"
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with float exponent SHOULD FAILS \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n7. run with float exponent SHOULD FAILS \n"$(RESET)
-./$(NAME) -d "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5 * x^1.2"
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with power 4 \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n8. run with power 4 \n"$(RESET)
-./$(NAME) -d "3x^2 + 2x -7x^4 = x^4"
@echo $(B_PURPLE)"\n---------------------------------------------\n5. run with utf8 \n"$(RESET)
@echo $(B_PURPLE)"\n---------------------------------------------\n9. run with utf8 \n"$(RESET)
-./$(NAME) -d "3x² + 2x -7x³ = x³"
clean:

View File

@@ -44,4 +44,21 @@ this project uses submodules (maybe recursively), so either :
5. find degree
6. print degree
7. solve
8. print solution
-> discriminant : Δ = b² - 4ac
-> Δ > 0 -> 2 solutions : x = ( -b / 2a ) +- ( √|Δ| / 2a )
-> Δ == 0 -> : x = ( -b / 2a )
-> Δ < 0 -> 2 solutions : x = ( -b / 2a ) +- i( √|Δ| / 2a )
-> solution :
- delta_sign; // + or -
- delta_absolute; // |Δ|
- first_term_pgcd; // pgcd(b, 2a)
- first_term_numerator; // -b / pgcd
- first_term_denominator; // 2a / pgcd
- first_term; // double (-b / 2a)
- second_term_pgcd; // pgcd(√|Δ|, 2a)
- second_term_numerator; // √|Δ| / pgcd
- second_term_denominator; // 2a / pgcd
- second_term; // double (√|Δ| / 2a)
- double solution1; // first_term + second_term
- double solution2; // first_term - second_term
8. print solution

View File

@@ -66,7 +66,7 @@ typedef struct
};
} s_token;
int lexerize(const char *input, s_token *tokens);
void lexerize(const char *input, s_token *tokens);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* PARSER.C
@@ -94,7 +94,7 @@ typedef struct
int exponent;
} s_term;
int parse(s_token *tokens, s_term *terms, int terms_count_max);
void parse(s_token *tokens, s_term *terms, int terms_count_max);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* REDUCE.C
@@ -102,6 +102,35 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max);
void reduce(s_term *terms, double *polynom);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SOLVE.C
*/
typedef enum
{
DELTA_PLUS, // +
DELTA_MINUS, // -
DELTA_ZERO, // 0
} e_delta_sign;
typedef struct
{
e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
double delta_absolute; // |Δ| == |b² - 4ac|
int first_term_pgcd; // pgcd(b, 2a)
int first_term_numerator; // -b / pgcd
int first_term_denominator; // 2a / pgcd
double first_term; // double (-b / 2a)
int second_term_pgcd; // pgcd(√|Δ|, 2a)
int second_term_numerator; // √|Δ| / pgcd
int second_term_denominator; // 2a / pgcd
double second_term; // double (√|Δ| / 2a)
double solution1; // first_term + second_term
double solution2; // first_term - second_term
} s_solution;
void solve(const double *polynom, s_solution *solution);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/ERRORS.C
*/
@@ -117,6 +146,7 @@ const char *token_type_to_str(e_token_type type);
const char *token_tag_to_str(e_token_tag tag);
const char *term_position_to_str(e_term_position pos);
const char *term_sign_to_str(e_term_sign sign);
const char *delta_sign_to_str(e_delta_sign sign);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/PRINTER.C
@@ -135,5 +165,6 @@ extern double *polynom_g_err;
extern int polynom_len_g_err;
extern bool flag_debug_mode;
extern bool flag_loop_mode;
extern s_solution *solution_g_err;
#endif

View File

@@ -100,7 +100,6 @@ static void polynom_fill_null(double *polynom, int len)
void launch_computorv1(char *input)
{
int ret;
int max_exponent;
size_t arg_len;
size_t terms_count_prediction;
@@ -115,11 +114,7 @@ void launch_computorv1(char *input)
s_token tokens[arg_len];
tokens_g_err = tokens;
tokens_fill_null(tokens, arg_len);
ret = lexerize(input, tokens);
if (ret == 0)
{
stop_errors("lexer returned 0 token");
}
lexerize(input, tokens);
// parse
terms_count_prediction = count_any_of(input, "-+=") + 2; // +1 for first term that can have no leading '+', +1 for last term == NULL
@@ -127,11 +122,7 @@ void launch_computorv1(char *input)
s_term terms[terms_count_prediction];
terms_g_err = terms;
terms_fill_null(terms, terms_count_prediction);
ret = parse(tokens, terms, terms_count_prediction);
if (ret == 0)
{
stop_errors("parser returned 0 term");
}
parse(tokens, terms, terms_count_prediction);
// reduce
max_exponent = get_max_exponent(terms) + 1;
@@ -142,6 +133,11 @@ void launch_computorv1(char *input)
reduce(terms, polynom);
// solve
s_solution solution[1];
solution_g_err = solution;
solve(polynom, solution);
// print solution
// debug
print_state();

View File

@@ -215,7 +215,7 @@ static bool token_is_equal(const char *input, int input_pos, int *token_size)
/**
* LEXER
*/
int lexerize(const char *input, s_token *tokens)
void lexerize(const char *input, s_token *tokens)
{
int tokens_count;
int input_pos;
@@ -308,6 +308,4 @@ int lexerize(const char *input, s_token *tokens)
tokens[tokens_count].type = TOKEN_END;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0';
return tokens_count;
}

View File

@@ -13,6 +13,7 @@ s_token *tokens_g_err;
s_term *terms_g_err;
double *polynom_g_err;
int polynom_len_g_err;
s_solution *solution_g_err;
/**
* PROGRAM
@@ -91,6 +92,8 @@ static void launch_stdin_loop()
{
while (1)
{
// for the moment it does not work since errors exit
launch_stdin();
}
}

View File

@@ -196,7 +196,7 @@ static void check_variables(s_token *tokens)
}
}
int parse(s_token *tokens, s_term *terms, int terms_count_max)
void parse(s_token *tokens, s_term *terms, int terms_count_max)
{
int i;
int terms_count;
@@ -265,6 +265,4 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max)
{
stop_errors("terms_count: %i, terms_count_max: %i, tokens[%i].type: %s", terms_count, terms_count_max, i, token_type_to_str(tokens[i].type));
}
return terms_count;
}

50
src/solver.c Normal file
View File

@@ -0,0 +1,50 @@
/* solver.c */
#include "computorv1.h"
/*
e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
double delta_absolute; // |Δ| == |b² - 4ac|
int first_term_pgcd; // pgcd(b, 2a)
int first_term_numerator; // -b / pgcd
int first_term_denominator; // 2a / pgcd
double first_term; // double (-b / 2a)
int second_term_pgcd; // pgcd(√|Δ|, 2a)
int second_term_numerator; // √|Δ| / pgcd
int second_term_denominator; // 2a / pgcd
double second_term; // double (√|Δ| / 2a)
double solution1; // first_term + second_term
double solution2; // first_term - second_term
*/
void solve(const double *polynom, s_solution *solution)
{
double delta;
double a;
double b;
double c;
a = polynom[2];
b = polynom[1];
c = polynom[0];
delta = b * b - 4 * a * c;
solution->delta_sign = ft_sign(delta);
solution->delta_absolute = ft_abs(delta);
// solution->first_term_pgcd = find_pgcd(b, 2 * a);
// solution->first_term_numerator = ;
// solution->first_term_denominator = ;
// solution->first_term = ;
// solution->second_term_pgcd = ;
// solution->second_term_numerator = ;
// solution->second_term_denominator = ;
// solution->second_term = ;
// solution->solution1 = solution->first_term;
// if (solution->delta_sign == DELTA_ZERO)
// {
// solution->solution2 = ;
// }
// else
// {
// solution->solution2 = 0.0;
// }
}

View File

@@ -15,33 +15,9 @@ static void print_context_tokens()
i = 0;
while (tokens_g_err[i].type != TOKEN_END)
{
ft_dprintf(STDERR_FILENO, "token[%2i] - type : ", i);
if (tokens_g_err[i].type == TOKEN_VARIABLE)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_VARIABLE");
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_INT");
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT_SUPER)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_INT_SUPER");
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_DOUBLE");
else if (tokens_g_err[i].type == TOKEN_POWER)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_POWER");
else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_SIGN_PLUS");
else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_SIGN_MINUS");
else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_FACTOR_MULT");
else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_FACTOR_DIV");
else if (tokens_g_err[i].type == TOKEN_EQUAL)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_EQUAL");
else if (tokens_g_err[i].type == TOKEN_END)
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_END");
ft_dprintf(STDERR_FILENO, "token[%2i] - type : %22s", i, token_type_to_str(tokens_g_err[i].type));
ft_putstr(" - value : ");
if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
{
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
@@ -71,29 +47,9 @@ static void print_context_terms()
while (terms_g_err[i].position != TERM_END)
{
ft_dprintf(STDERR_FILENO, "term[%2i] - ", i);
// position
ft_dprintf(STDERR_FILENO, "%8s : ", "position");
if (terms_g_err[i].position == TERM_LEFT)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_LEFT");
else if (terms_g_err[i].position == TERM_RIGHT)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_RIGHT");
else
ft_dprintf(STDERR_FILENO, "%10s", "");
// sign
ft_dprintf(STDERR_FILENO, " | %4s : ", "sign");
if (terms_g_err[i].sign == TERM_PLUS)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_PLUS");
else if (terms_g_err[i].sign == TERM_MINUS)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_MINUS");
else
ft_dprintf(STDERR_FILENO, "%10s", "");
// coefficient
ft_dprintf(STDERR_FILENO, "%8s : %10s", "position", term_position_to_str(terms_g_err[i].position));
ft_dprintf(STDERR_FILENO, " | %4s : %10s", "sign", term_sign_to_str(terms_g_err[i].sign));
dprintf(STDERR_FILENO, " | %10s : %13g", "coefficient", terms_g_err[i].coefficient);
// exponent
ft_dprintf(STDERR_FILENO, " | %8s : %d\n", "exponent", terms_g_err[i].exponent);
i++;
}
@@ -110,6 +66,25 @@ static void print_context_polynom()
dprintf(STDERR_FILENO, "polynom[%i]: %10g\n", i, polynom_g_err[i]);
i++;
}
ft_putchar_fd('\n', STDERR_FILENO);
}
static void print_context_solution()
{
dprintf(STDERR_FILENO, "delta_sign : %25s\n", delta_sign_to_str(solution_g_err->delta_sign));
dprintf(STDERR_FILENO, "delta_absolute : %25g\n", solution_g_err->delta_absolute);
// dprintf(STDERR_FILENO, "first_term_pgcd : %25g\n", solution_g_err->first_term_pgcd);
// dprintf(STDERR_FILENO, "first_term_numerator : %25g\n", solution_g_err->first_term_numerator);
// dprintf(STDERR_FILENO, "first_term_denominator : %25g\n", solution_g_err->first_term_denominator);
// dprintf(STDERR_FILENO, "first_term : %25g\n", solution_g_err->first_term);
// dprintf(STDERR_FILENO, "second_term_pgcd : %25g\n", solution_g_err->second_term_pgcd);
// dprintf(STDERR_FILENO, "second_term_numerator : %25g\n", solution_g_err->second_term_numerator);
// dprintf(STDERR_FILENO, "second_term_denominator: %25g\n", solution_g_err->second_term_denominator);
// dprintf(STDERR_FILENO, "second_term : %25g\n", solution_g_err->second_term);
// dprintf(STDERR_FILENO, "solution1 : %25g\n", solution_g_err->solution1);
// dprintf(STDERR_FILENO, "solution2 : %25g\n", solution_g_err->solution2);
ft_putchar_fd('\n', STDERR_FILENO);
}
void print_state()
@@ -125,6 +100,8 @@ void print_state()
print_context_terms();
if (polynom_g_err)
print_context_polynom();
if (solution_g_err)
print_context_solution();
}
void stop_errors(const char *description, ...)

View File

@@ -11,6 +11,7 @@ const char *token_type_to_str(e_token_type enum_value)
[TOKEN_VARIABLE] = "TOKEN_VARIABLE",
[TOKEN_NUMBER_INT] = "TOKEN_NUMBER_INT",
[TOKEN_NUMBER_DOUBLE] = "TOKEN_NUMBER_DOUBLE",
[TOKEN_NUMBER_INT_SUPER] = "TOKEN_NUMBER_INT_SUPER",
[TOKEN_POWER] = "TOKEN_POWER",
[TOKEN_SIGN_PLUS] = "TOKEN_SIGN_PLUS",
[TOKEN_SIGN_MINUS] = "TOKEN_SIGN_MINUS",
@@ -56,4 +57,16 @@ const char *term_sign_to_str(e_term_sign enum_value)
[TERM_MINUS] = "TERM_MINUS",
[TERM_NULL] = "TERM_NULL"};
return term_sign_str[enum_value];
}
const char *delta_sign_to_str(e_delta_sign enum_value)
{
if (enum_value > DELTA_ZERO || enum_value < DELTA_PLUS)
return "invalid enum value";
static const char *const delta_sign_str[DELTA_ZERO + 1] = {
[DELTA_PLUS] = "DELTA_PLUS",
[DELTA_MINUS] = "DELTA_MINUS",
[DELTA_ZERO] = "DELTA_ZERO"};
return delta_sign_str[enum_value];
}

View File

@@ -10,7 +10,7 @@ void print_debug(const char *description, ...)
// print the formatted description
va_list args;
va_start(args, description);
// ft_vdprintf(STDOUT_FILENO, description, args);
// ft_vdprintf(STDOUT_FILENO, description, args); // it's not handling floats for the moment
vdprintf(STDOUT_FILENO, description, args);
va_end(args);
}