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 \ lexer.c \
parser.c \ parser.c \
reducer.c \ reducer.c \
solver.c \
errors.c \ errors.c \
printer.c \ printer.c \
print_enums.c print_enums.c
@@ -98,23 +99,23 @@ $(NAME): $(OBJS)
$(CC) $(OBJS) -o $@ $(LFLAGS) $(CC) $(OBJS) -o $@ $(LFLAGS)
run: $(NAME) 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" -./$(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 -./$(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) @echo $(B_PURPLE)"\n---------------------------------------------\n3. run with flag '-d' as first \n"$(RESET)
-./$(NAME) -d "3 * x^2 + 2 * x^2 = 5 * x^1" -./$(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) @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" -./$(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" -./$(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" -./$(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" -./$(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" -./$(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³" -./$(NAME) -d "3x² + 2x -7x³ = x³"
clean: clean:

View File

@@ -44,4 +44,21 @@ this project uses submodules (maybe recursively), so either :
5. find degree 5. find degree
6. print degree 6. print degree
7. solve 7. solve
-> 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 8. print solution

View File

@@ -66,7 +66,7 @@ typedef struct
}; };
} s_token; } s_token;
int lexerize(const char *input, s_token *tokens); void lexerize(const char *input, s_token *tokens);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* PARSER.C * PARSER.C
@@ -94,7 +94,7 @@ typedef struct
int exponent; int exponent;
} s_term; } 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 * 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); 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 * 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 *token_tag_to_str(e_token_tag tag);
const char *term_position_to_str(e_term_position pos); const char *term_position_to_str(e_term_position pos);
const char *term_sign_to_str(e_term_sign sign); const char *term_sign_to_str(e_term_sign sign);
const char *delta_sign_to_str(e_delta_sign sign);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/PRINTER.C * UTILS/PRINTER.C
@@ -135,5 +165,6 @@ extern double *polynom_g_err;
extern int polynom_len_g_err; extern int polynom_len_g_err;
extern bool flag_debug_mode; extern bool flag_debug_mode;
extern bool flag_loop_mode; extern bool flag_loop_mode;
extern s_solution *solution_g_err;
#endif #endif

View File

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

View File

@@ -215,7 +215,7 @@ static bool token_is_equal(const char *input, int input_pos, int *token_size)
/** /**
* LEXER * LEXER
*/ */
int lexerize(const char *input, s_token *tokens) void lexerize(const char *input, s_token *tokens)
{ {
int tokens_count; int tokens_count;
int input_pos; int input_pos;
@@ -308,6 +308,4 @@ int lexerize(const char *input, s_token *tokens)
tokens[tokens_count].type = TOKEN_END; tokens[tokens_count].type = TOKEN_END;
tokens[tokens_count].tag = TOKEN_NO_TAG; tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0'; 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; s_term *terms_g_err;
double *polynom_g_err; double *polynom_g_err;
int polynom_len_g_err; int polynom_len_g_err;
s_solution *solution_g_err;
/** /**
* PROGRAM * PROGRAM
@@ -91,6 +92,8 @@ static void launch_stdin_loop()
{ {
while (1) 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 i;
int terms_count; 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)); 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; i = 0;
while (tokens_g_err[i].type != TOKEN_END) while (tokens_g_err[i].type != TOKEN_END)
{ {
ft_dprintf(STDERR_FILENO, "token[%2i] - type : ", i); ft_dprintf(STDERR_FILENO, "token[%2i] - type : %22s", i, token_type_to_str(tokens_g_err[i].type));
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_putstr(" - value : "); ft_putstr(" - value : ");
if (tokens_g_err[i].type == TOKEN_NUMBER_INT) if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
{ {
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_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) while (terms_g_err[i].position != TERM_END)
{ {
ft_dprintf(STDERR_FILENO, "term[%2i] - ", i); ft_dprintf(STDERR_FILENO, "term[%2i] - ", i);
ft_dprintf(STDERR_FILENO, "%8s : %10s", "position", term_position_to_str(terms_g_err[i].position));
// position ft_dprintf(STDERR_FILENO, " | %4s : %10s", "sign", term_sign_to_str(terms_g_err[i].sign));
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
dprintf(STDERR_FILENO, " | %10s : %13g", "coefficient", terms_g_err[i].coefficient); 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); ft_dprintf(STDERR_FILENO, " | %8s : %d\n", "exponent", terms_g_err[i].exponent);
i++; i++;
} }
@@ -110,6 +66,25 @@ static void print_context_polynom()
dprintf(STDERR_FILENO, "polynom[%i]: %10g\n", i, polynom_g_err[i]); dprintf(STDERR_FILENO, "polynom[%i]: %10g\n", i, polynom_g_err[i]);
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() void print_state()
@@ -125,6 +100,8 @@ void print_state()
print_context_terms(); print_context_terms();
if (polynom_g_err) if (polynom_g_err)
print_context_polynom(); print_context_polynom();
if (solution_g_err)
print_context_solution();
} }
void stop_errors(const char *description, ...) 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_VARIABLE] = "TOKEN_VARIABLE",
[TOKEN_NUMBER_INT] = "TOKEN_NUMBER_INT", [TOKEN_NUMBER_INT] = "TOKEN_NUMBER_INT",
[TOKEN_NUMBER_DOUBLE] = "TOKEN_NUMBER_DOUBLE", [TOKEN_NUMBER_DOUBLE] = "TOKEN_NUMBER_DOUBLE",
[TOKEN_NUMBER_INT_SUPER] = "TOKEN_NUMBER_INT_SUPER",
[TOKEN_POWER] = "TOKEN_POWER", [TOKEN_POWER] = "TOKEN_POWER",
[TOKEN_SIGN_PLUS] = "TOKEN_SIGN_PLUS", [TOKEN_SIGN_PLUS] = "TOKEN_SIGN_PLUS",
[TOKEN_SIGN_MINUS] = "TOKEN_SIGN_MINUS", [TOKEN_SIGN_MINUS] = "TOKEN_SIGN_MINUS",
@@ -57,3 +58,15 @@ const char *term_sign_to_str(e_term_sign enum_value)
[TERM_NULL] = "TERM_NULL"}; [TERM_NULL] = "TERM_NULL"};
return term_sign_str[enum_value]; 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 // print the formatted description
va_list args; va_list args;
va_start(args, description); 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); vdprintf(STDOUT_FILENO, description, args);
va_end(args); va_end(args);
} }