From c99bdfc63a70f88ad8dafa77e82e1339610871d6 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 26 May 2026 12:48:36 +0200 Subject: [PATCH] fix number tokens and limits --- .vscode/settings.json | 3 + README.md | 169 +++++++------- src/launcher.c | 8 +- src/lexer.c | 522 ++++++++++++++++++++++-------------------- src/main.c | 266 +++++++++++---------- src/parser.c | 24 +- src/utils/math.c | 2 +- tester.sh | 64 ++++++ 8 files changed, 577 insertions(+), 481 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ab01ac6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "window.title": "${rootName} — ${activeEditorShort}" +} diff --git a/README.md b/README.md index 4ebafd8..18f1e0a 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,28 @@ # 42_EXT_05_computorv1 +## todo + +- [ ] arg limit ? +- [x] change order is_number_int and is_number_double +- [x] remove double limit in lexer +- [ ] check why number stored in int or double +- [x] get rid of lib math (check in libft) +- [x] use ft_abs() instead of abs() -> actually abs() is in stdlib +- [x] handling sign '-' : "+ -2" +- [x] max exponent len : ## ressources -- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1 -- project luke : https://github.com/LuckyLaszlo/computorv1 +- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1 +- project luke : https://github.com/LuckyLaszlo/computorv1 ## install -this project uses submodules (maybe recursively), so either : +this project uses submodules (maybe recursively), so either : - `git clone --recurse-submodules ` - or, after cloning : `git submodule update --init --recursive` - --- # sqrt implementation @@ -24,7 +33,7 @@ finding the square root of x the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration. -Ex : +Ex : ``` solution @@ -57,12 +66,11 @@ Ex : --------|---------------------- --> solution ``` - ## Newton–Raphson method it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae `x/v` to find the next range, with `x` being the number we are trying to get the sqaure root from, and `v` the value found at the previous step. -Ex : +Ex : ``` solution @@ -91,87 +99,72 @@ Ex : ``` ### mathematical proof that each range is automatically in the right range : - - if the value was higher than the answer, then new value is below old value, and vice versa - - how ? : - - define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2` - - supposition : if `v < s` , then `new_v > v`, else `new_v < v` : - - demonstration : - 1. if `v < s` : - v < s - <=> v < √x - <=> v² < x (that's actually how we know that v < s) - <=> v²/v < x/v - <=> v < x/v - -> and is s < x/v ? : - v < s - <=> v < √x - <=> v² < x (as previously) - <=> v² < x²/x - <=> v² * x < x² - <=> (v * √x)² < x² - <=> v * √x < x - <=> v * √x < v * x/v - <=> √x < x/v - -> so indeed : if v < √x, then v < √x < x/v == v < s < x/v - -> conclusion, the new range < v , x/v > contains the solution - 2. the same demonstration works for `v > s` -### here is a more intuitive demonstration, with x = 20 : +- if the value was higher than the answer, then new value is below old value, and vice versa +- how ? : + - define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2` + - supposition : if `v < s` , then `new_v > v`, else `new_v < v` : + - demonstration : + 1. if `v < s` : + v < s + <=> v < √x + <=> v² < x (that's actually how we know that v < s) + <=> v²/v < x/v + <=> v < x/v + -> and is s < x/v ? : + v < s + <=> v < √x + <=> v² < x (as previously) + <=> v² < x²/x + <=> v² _ x < x² + <=> (v _ √x)² < x² + <=> v _ √x < x + <=> v _ √x < v \* x/v + <=> √x < x/v + -> so indeed : if v < √x, then v < √x < x/v == v < s < x/v + -> conclusion, the new range < v , x/v > contains the solution + 2. the same demonstration works for `v > s` + +### here is a more intuitive demonstration, with x = 20 : 1. **show that if `v² > x` (== `v > s`) then `v > s > x/v`, and if `v² < x` (== `v < s`) then `v < s < x/v` :** - 1.1. **for value too high `v > s` :** - 1.1.1 **why `v > x/v` :** - - let's take initial value v = 5 : - - is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high - ``` - v v² - 0 (5) 10 15 20 25 - v : |----|----|----|----|----| - x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size - 0 (4) 8 12 16 20 - x/v x - ``` - - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5 - - so : `v > x/v` - 1.1.2 **why `s > x/v` :** - - let's take the value v = 5 : - - we already showed that it's too high, now we will see that x/v == 20/5 is too low : - ``` - v - 0 (5) 10 15 20 25 - v : |----|----|----|----|----| - x/v: |---|---|---|---|---| <----- squizz - 0 *1 *2 *3 *4 *5 -> number of portions - 01234 -> portion size - (x/v)²: |---|---|---|---| - 0 4 8 12 16 - ``` - - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16` - - so : `s > x/v` - 1.1.3. **conclusion :** - - v > s - - and v > x/v (<- this proof is not essential) - - and s > x/v (<- we actually only need this proof) - - so `v > s > x/v` - - 1.2. **for value too high `v < s` :** - - this is the same demonstration but in other direction, let's just summarize it : - - let's take initial value v = 4 : - ``` - v v² - 0 (4) 8 12 16 - (1) v : |---|---|---|---| - (2) x/v: |----|----|----|----| -----> stretch - (3) 0 (5) 10 15 20 - x/v x - (4) 0 *1 *2 *3 *4 -> number of portions - 012345 -> portion size - (5) (x/v)²: |----|----|----|----|----| - 0 5 10 15 20 25 - ``` - - (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20 - - (2) : stretch it, so the previous 4 portions fit the x = 20 size - - (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v` - - (4) : portion size is bigger than number of portions, so it's too big to be the root - - (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v` - - so `v < s < x/v` + 1.1. **for value too high `v > s` :** + 1.1.1 **why `v > x/v` :** - let's take initial value v = 5 : - is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high + ` v v² + 0 (5) 10 15 20 25 +v : |----|----|----|----|----| +x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size + 0 (4) 8 12 16 20 + x/v x` - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5 - so : `v > x/v` + 1.1.2 **why `s > x/v` :** - let's take the value v = 5 : - we already showed that it's too high, now we will see that x/v == 20/5 is too low : + ` v + 0 (5) 10 15 20 25 +v : |----|----|----|----|----| +x/v: |---|---|---|---|---| <----- squizz + 0 *1 *2 *3 *4 *5 -> number of portions + 01234 -> portion size +(x/v)²: |---|---|---|---| + 0 4 8 12 16` - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16` - so : `s > x/v` + 1.1.3. **conclusion :** - v > s - and v > x/v (<- this proof is not essential) - and s > x/v (<- we actually only need this proof) - so `v > s > x/v` + + 1.2. **for value too high `v < s` :** + - this is the same demonstration but in other direction, let's just summarize it : + - let's take initial value v = 4 : + ``` + v v² + 0 (4) 8 12 16 + (1) v : |---|---|---|---| + (2) x/v: |----|----|----|----| -----> stretch + (3) 0 (5) 10 15 20 + x/v x + (4) 0 *1 *2 *3 *4 -> number of portions + 012345 -> portion size + (5) (x/v)²: |----|----|----|----|----| + 0 5 10 15 20 25 + ``` + - (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20 + - (2) : stretch it, so the previous 4 portions fit the x = 20 size + - (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v` + - (4) : portion size is bigger than number of portions, so it's too big to be the root + - (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v` + - so `v < s < x/v` diff --git a/src/launcher.c b/src/launcher.c index 6f946db..f636ef8 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -91,7 +91,7 @@ void launch_computorv1(char *input) int max_exponent; int nbr_of_exponents; int degree; - size_t arg_len; + size_t token_len; size_t terms_count_prediction; // init @@ -99,9 +99,9 @@ void launch_computorv1(char *input) remove_spaces(input); // lexerize - arg_len = ft_strlen(input) + 1; // +1 for last END token - print_debug("\n-> tokens[%i]\n", arg_len); - s_token tokens[arg_len]; + token_len = ft_strlen(input) + 1; // +1 for last END token + print_debug("\n-> tokens[%i]\n", token_len); + s_token tokens[token_len]; tokens_g_err = tokens; ft_bzero(tokens, sizeof(tokens)); lexerize(input, tokens); diff --git a/src/lexer.c b/src/lexer.c index 683cce0..404c4d3 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -2,316 +2,344 @@ #include "computorv1.h" +/** + * INT CHECKS + */ + +static bool is_number_bigger_than_int_max(const char *input, int size) +{ + const char *int_max_str = "2147483647"; + int int_max_len = ft_strlen(int_max_str); + + if (size < int_max_len) + return false; + if (size > int_max_len) + return true; + + return ft_strncmp(input, int_max_str, int_max_len) > 0; +} +static bool is_number_smaller_than_int_min(const char *input, int size) +{ + const char *int_min_str = "-2147483648"; + int int_min_len = ft_strlen(int_min_str); + + if (size < int_min_len) + return false; + if (size > int_min_len) + return true; + + return ft_strncmp(input, int_min_str, int_min_len) < 0; +} +static bool is_number_out_of_int_range(const char *input, int size) +{ + if (input[0] == '-') + { + return is_number_smaller_than_int_min(input, size); + } + else + { + return is_number_bigger_than_int_max(input, size); + } +} + +/** + * TOKEN CHECKS + */ + // token is alphabet letter, like 'x' or 'y' static bool token_is_variable(const char *input, int input_pos, int *token_size) { - if (ft_isalpha(input[input_pos])) - { - *token_size = 1; - return true; - } - return false; + if (ft_isalpha(input[input_pos])) + { + *token_size = 1; + return true; + } + return false; } // token is int "123" static bool token_is_number_int(const char *input, int input_pos, int *token_size) { - int number_size; - int max_number_size; + int number_size; - if (!ft_isdigit(input[input_pos])) - { - return false; - } + number_size = 0; - number_size = 1; - max_number_size = 16; // max size for int - while (number_size <= max_number_size) - { - if (ft_isdigit(input[input_pos + number_size])) - { - number_size++; - } - else if (input[input_pos + number_size] == '.') - { - if (ft_isdigit(input[input_pos + number_size + 1])) - { - // number is double - return false; - } - else - break; - } - else - break; - } - if (number_size > max_number_size) - { - stop_errors(&input[input_pos]); - } - *token_size = number_size; - return true; + // if (input[input_pos + number_size] == '-') + // number_size++; + + while (input[input_pos + number_size] != '\0') + { + if (ft_isdigit(input[input_pos + number_size])) + { + number_size++; + } + else + break; + } + if (number_size == 0) + { + return false; + } + if (is_number_out_of_int_range(&input[input_pos], number_size)) + { + return false; + } + *token_size = number_size; + return true; } -// token is double "123.456" +// token is double "123.456" or token < MIN_INT or token > MAX_INT static bool token_is_number_double(const char *input, int input_pos, int *token_size) { - int number_size; - int max_number_size; - bool has_dot; + int number_size; + bool has_dot; - if (!ft_isdigit(input[input_pos])) - { - return false; - } + has_dot = false; + number_size = 0; - has_dot = false; - number_size = 1; - max_number_size = 24; // max char needed to represent double : 1 sign + 1 point + 17 fractinoal part + 5 exponent - while (number_size <= max_number_size) - { - if (ft_isdigit(input[input_pos + number_size])) - { - number_size++; - } - else if (input[input_pos + number_size] == '.') - { - if (has_dot) - { - // number is not a valid token, it has 2 dots - return false; - } - if (!ft_isdigit(input[input_pos + number_size + 1])) - { - // number is not valid token, it has a dot with no number after the dot - return false; - } - has_dot = true; - number_size++; - } - else - break; - } - if (number_size > max_number_size) - { - stop_errors(&input[input_pos]); - } - *token_size = number_size; - return true; + // if (input[input_pos + number_size] == '-') + // number_size++; + + while (input[input_pos + number_size] != '\0') + { + if (ft_isdigit(input[input_pos + number_size])) + { + number_size++; + } + else if (input[input_pos + number_size] == '.' && !has_dot) + { + has_dot = true; + number_size++; + } + else + break; + } + if (is_number_out_of_int_range(&input[input_pos], number_size)) + { + *token_size = number_size; + return true; + } + if (!has_dot) + { + return false; + } + + *token_size = number_size; + return true; } -// token is superscript int (e.g., ¹, ², ³, ⁴, ⁵, etc.) +// token is superscript int e.g. ¹, ², ³, ⁴, ⁵, ⁶⁶⁶ static bool token_is_number_int_super(const char *input, int input_pos, int *token_size) { - int digit_size = 0; - int number_size = 0; - int max_number_size = 16; // same max size as regular integers + int digit_size = 0; + int number_size = 0; + int superscript_len = 0; + int superscript_len_max = 3; // max length of superscript int we want to support - // check if first character is superscript - if (!ft_isdigit_superscript(input + input_pos, NULL)) - { - return false; - } + // iterate to find full superscript number + while (input[input_pos + number_size] != '\0') + { + if (ft_isdigit_superscript(&input[input_pos + number_size], &digit_size)) + { + superscript_len++; + // Increment by the length of the UTF-8 character (2 or 3 bytes) + number_size += digit_size; + } + else + { + break; + } + } + if (number_size == 0) + { + return false; + } + if (superscript_len > superscript_len_max) + { + stop_errors("superscript int is too long (max supported length is %d), got : %s\n", superscript_len_max, &input[input_pos]); + } - // iterate to find full superscript number - while (number_size < max_number_size) - { - if (ft_isdigit_superscript(input + input_pos + number_size, &digit_size)) - { - // Increment by the length of the UTF-8 character (2 or 3 bytes) - number_size += digit_size; - } - else - { - break; - } - } - - if (number_size == 0) - { - return false; - } - - *token_size = number_size; - return true; + *token_size = number_size; + return true; } // token is '^' or "**" static bool token_is_power(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '^') - { - *token_size = 1; - return true; - } - if (ft_memcmp(&input[input_pos], "**", 2) == 0) - { - *token_size = 2; - return true; - } - return false; + if (input[input_pos] == '^') + { + *token_size = 1; + return true; + } + if (ft_memcmp(&input[input_pos], "**", 2) == 0) + { + *token_size = 2; + return true; + } + return false; } // token is '+' static bool token_is_sign_plus(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '+') - { - *token_size = 1; - return true; - } - return false; + if (input[input_pos] == '+') + { + *token_size = 1; + return true; + } + return false; } // token is '-' static bool token_is_sign_minus(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '-') - { - *token_size = 1; - return true; - } - return false; + if (input[input_pos] == '-') + { + *token_size = 1; + return true; + } + return false; } // token is '*' static bool token_is_factor_multiplication(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '*') - { - *token_size = 1; - return true; - } - return false; + if (input[input_pos] == '*') + { + *token_size = 1; + return true; + } + return false; } // token is '/' or ':' static bool token_is_factor_division(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '/') - { - *token_size = 1; - return true; - } - if (input[input_pos] == ':') - { - *token_size = 1; - return true; - } - return false; + if (input[input_pos] == '/') + { + *token_size = 1; + return true; + } + if (input[input_pos] == ':') + { + *token_size = 1; + return true; + } + return false; } // token is '=' static bool token_is_equal(const char *input, int input_pos, int *token_size) { - if (input[input_pos] == '=') - { - *token_size = 1; - return true; - } - return false; + if (input[input_pos] == '=') + { + *token_size = 1; + return true; + } + return false; } /** * LEXER */ + void lexerize(const char *input, s_token *tokens) { - int tokens_count; - int input_pos; - int token_size; - bool has_equal; + int tokens_count; + int input_pos; + int token_size; + bool has_equal; - has_equal = false; - tokens_count = 0; - input_pos = 0; - while (input[input_pos]) - { - token_size = 0; + has_equal = false; + tokens_count = 0; + input_pos = 0; + while (input[input_pos]) + { + token_size = 0; - if (input[input_pos] == '\0') - { - break; - } + if (input[input_pos] == '\0') + { + break; + } - if (token_is_variable(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_VARIABLE; - tokens[tokens_count].tag = TOKEN_NO_TAG; - tokens[tokens_count].value_char = 'x'; - } - else if (token_is_number_int(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_NUMBER_INT; - tokens[tokens_count].tag = TOKEN_NUMBER; - tokens[tokens_count].value_int = ft_atoi(&input[input_pos]); - } - else if (token_is_number_double(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE; - tokens[tokens_count].tag = TOKEN_NUMBER; - tokens[tokens_count].value_double = ft_atof(&input[input_pos]); - } - else if (token_is_number_int_super(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER; - tokens[tokens_count].tag = TOKEN_NUMBER; - tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]); - } - else if (token_is_power(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_POWER; - tokens[tokens_count].tag = TOKEN_NO_TAG; - tokens[tokens_count].value_char = '^'; - } - else if (token_is_sign_plus(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_SIGN_PLUS; - tokens[tokens_count].tag = TOKEN_SIGN; - tokens[tokens_count].value_char = input[input_pos]; - } - else if (token_is_sign_minus(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_SIGN_MINUS; - tokens[tokens_count].tag = TOKEN_SIGN; - tokens[tokens_count].value_char = input[input_pos]; - } - else if (token_is_factor_multiplication(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_FACTOR_MULT; - tokens[tokens_count].tag = TOKEN_FACTOR; - tokens[tokens_count].value_char = input[input_pos]; - } - else if (token_is_factor_division(input, input_pos, &token_size)) - { - tokens[tokens_count].type = TOKEN_FACTOR_DIV; - tokens[tokens_count].tag = TOKEN_FACTOR; - tokens[tokens_count].value_char = input[input_pos]; - } - else if (token_is_equal(input, input_pos, &token_size)) - { - has_equal = true; - tokens[tokens_count].type = TOKEN_EQUAL; - tokens[tokens_count].tag = TOKEN_NO_TAG; - tokens[tokens_count].value_char = '='; - } - else - { - stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]); - } + if (token_is_variable(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_VARIABLE; + tokens[tokens_count].tag = TOKEN_NO_TAG; + tokens[tokens_count].value_char = 'x'; + } + else if (token_is_number_double(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE; + tokens[tokens_count].tag = TOKEN_NUMBER; + tokens[tokens_count].value_double = ft_atof(&input[input_pos]); + } + else if (token_is_number_int(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_NUMBER_INT; + tokens[tokens_count].tag = TOKEN_NUMBER; + tokens[tokens_count].value_int = ft_atoi(&input[input_pos]); + } + else if (token_is_number_int_super(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER; + tokens[tokens_count].tag = TOKEN_NUMBER; + tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]); + } + else if (token_is_power(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_POWER; + tokens[tokens_count].tag = TOKEN_NO_TAG; + tokens[tokens_count].value_char = '^'; + } + else if (token_is_sign_plus(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_SIGN_PLUS; + tokens[tokens_count].tag = TOKEN_SIGN; + tokens[tokens_count].value_char = input[input_pos]; + } + else if (token_is_sign_minus(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_SIGN_MINUS; + tokens[tokens_count].tag = TOKEN_SIGN; + tokens[tokens_count].value_char = input[input_pos]; + } + else if (token_is_factor_multiplication(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_FACTOR_MULT; + tokens[tokens_count].tag = TOKEN_FACTOR; + tokens[tokens_count].value_char = input[input_pos]; + } + else if (token_is_factor_division(input, input_pos, &token_size)) + { + tokens[tokens_count].type = TOKEN_FACTOR_DIV; + tokens[tokens_count].tag = TOKEN_FACTOR; + tokens[tokens_count].value_char = input[input_pos]; + } + else if (token_is_equal(input, input_pos, &token_size)) + { + has_equal = true; + tokens[tokens_count].type = TOKEN_EQUAL; + tokens[tokens_count].tag = TOKEN_NO_TAG; + tokens[tokens_count].value_char = '='; + } + else + { + stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]); + } - tokens_count++; - if (token_size == 0) - { - stop_errors("token_size is 0 : %s\n", &input[input_pos]); - } - input_pos += token_size; - } + tokens_count++; + if (token_size == 0) + { + stop_errors("token_size is 0 : %s\n", &input[input_pos]); + } + input_pos += token_size; + } - if (!has_equal) - stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n"); + if (!has_equal) + stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n"); - tokens[tokens_count].type = TOKEN_END; - tokens[tokens_count].tag = TOKEN_NO_TAG; - tokens[tokens_count].value_char = '\0'; + tokens[tokens_count].type = TOKEN_END; + tokens[tokens_count].tag = TOKEN_NO_TAG; + tokens[tokens_count].value_char = '\0'; } diff --git a/src/main.c b/src/main.c index cc14f25..dbb4e18 100644 --- a/src/main.c +++ b/src/main.c @@ -21,167 +21,161 @@ s_solution *solution_g_err; static void print_usage() { - ft_printf("USAGE :\n\n"); - ft_printf("| ./computorv1 [flags] [polynom]\n"); - ft_printf("| ./computorv1 [polynom] [flags]\n"); - ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n"); - ft_printf("[flags] :\n"); - ft_printf("-d : print debug\n"); - ft_printf("-l : interactive loop\n"); - ft_printf("-b : beautify output\n"); - ft_putchar('\n'); + ft_printf("USAGE :\n\n"); + ft_printf("| ./computorv1 [flags] [polynom]\n"); + ft_printf("| ./computorv1 [polynom] [flags]\n"); + ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n"); + ft_printf("[flags] :\n"); + ft_printf("-d : print debug\n"); + ft_printf("-l : interactive loop\n"); + ft_printf("-b : beautify output\n"); + ft_putchar('\n'); } // trim spaces and quotes and newlines static void clean_copy_input(char *input, char *line) { - size_t i; - size_t j; - size_t len; - size_t len_trim_end; - size_t len_trim_start; + size_t i; + size_t j; + size_t len; + size_t len_trim_end; + size_t len_trim_start; - len = ft_strlen(line); + len = ft_strlen(line); - // get len minus : ' | " | \n | - i = len; - while (i > 0) - { - if (ft_strchr("\"\'\n", line[i])) - i--; - if (ft_isspace(line[i])) - i--; - break; - } - len_trim_end = i; + // get len minus : ' | " | \n | + i = len; + while (i > 0) + { + if (ft_strchr("\"\'\n", line[i])) + i--; + if (ft_isspace(line[i])) + i--; + break; + } + len_trim_end = i; - // get len of leading chars : ' | " | | \n - i = 0; - while (i < len_trim_end) - { - if (ft_strchr("\"\'\n", line[i])) - i++; - if (ft_isspace(line[i])) - i++; - break; - } - len_trim_start = i; + // get len of leading chars : ' | " | | \n + i = 0; + while (i < len_trim_end) + { + if (ft_strchr("\"\'\n", line[i])) + i++; + if (ft_isspace(line[i])) + i++; + break; + } + len_trim_start = i; - // copy into input - i = len_trim_start; - j = 0; - while (i <= len_trim_end) - { - input[j] = line[i]; - j++; - i++; - } - input[j] = '\0'; + // copy into input + i = len_trim_start; + j = 0; + while (i <= len_trim_end) + { + input[j] = line[i]; + j++; + i++; + } + input[j] = '\0'; } static void launch_stdin() { - char *line; - size_t len; + char *line; + size_t len; - line = NULL; - len = 0; + line = NULL; + len = 0; - // get input - getline(&line, &len, stdin); + // get input + getline(&line, &len, stdin); - // prepare input - char input[len]; - clean_copy_input(input, line); + // prepare input + char input[len]; + clean_copy_input(input, line); - // launch input - launch_computorv1(input); + // launch input + launch_computorv1(input); - // FREE LINE ! - free(line); + // FREE LINE ! + free(line); } -static void launch_stdin_loop() -{ - while (1) - { - // for the moment it does not work since errors exit - launch_stdin(); - } -} +// static void launch_stdin_loop() +// { +// while (1) +// { +// // for the moment it does not work since errors exit +// launch_stdin(); +// } +// } int main(int ac, char **av) { - int i; - char *input; - e_program_mode program_mode; + int i; + char *input; + e_program_mode program_mode; - // init flags - flag_debug_mode = false; - flag_loop_mode = false; - flag_beautify_mode = false; + // init flags + flag_debug_mode = false; + flag_loop_mode = false; + flag_beautify_mode = false; - // check arguments - program_mode = MODE_ARGV; - if (ac == 1) - { - program_mode = MODE_STDIN; - } - else if (ac > 1) - { - // get flags - input = NULL; - i = 1; - while (i < ac) - { - if ((ft_strcmp(av[i], "-d") == 0)) - { - // flag -d : debug - flag_debug_mode = true; - } - else if ((ft_strcmp(av[i], "-l") == 0)) - { - // flag -l : interactiv loop - flag_loop_mode = true; - program_mode = MODE_LOOP; - } - else if ((ft_strcmp(av[i], "-b") == 0)) - { - // flag -b : beautify output - flag_beautify_mode = true; - } - else if (ft_strlen(av[i]) == 2 && av[i][0] == '-') - { - // unknown flag - print_usage(); - stop_errors("unknwon flag '%s'", av[i]); - } - else - { - input = av[i]; - } - i++; - } - // if input was not set, it means interactiv mode - if (input == NULL) - { - program_mode = MODE_STDIN; - } - } + // check arguments + program_mode = MODE_ARGV; - // launch calculator - if (program_mode == MODE_ARGV) - { - launch_computorv1(input); - } - else if (program_mode == MODE_STDIN) - { - launch_stdin(); - } - else if (program_mode == MODE_LOOP) - { - launch_stdin_loop(); - } + // get flags + input = NULL; + i = 1; + while (i < ac) + { + if ((ft_strcmp(av[i], "-d") == 0)) + { + // flag -d : debug + flag_debug_mode = true; + } + else if ((ft_strcmp(av[i], "-l") == 0)) + { + // flag -l : interactiv loop + flag_loop_mode = true; + program_mode = MODE_LOOP; + } + else if ((ft_strcmp(av[i], "-b") == 0)) + { + // flag -b : beautify output + flag_beautify_mode = true; + } + else if (ft_strlen(av[i]) == 2 && av[i][0] == '-') + { + // unknown flag + print_usage(); + stop_errors("unknwon flag '%s'", av[i]); + } + else + { + input = av[i]; + } + i++; + } + // if input was not set, it means interactiv mode + if (input == NULL) + { + program_mode = MODE_STDIN; + } - return (0); + // launch calculator + if (program_mode == MODE_ARGV) + { + launch_computorv1(input); + } + else if (program_mode == MODE_STDIN) + { + launch_stdin(); + } + // else if (program_mode == MODE_LOOP) + // { + // launch_stdin_loop(); + // } + + return (0); } diff --git a/src/parser.c b/src/parser.c index 6d1ddf8..6b7477e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -16,30 +16,44 @@ static e_term_sign get_sign(s_token *tokens, int i, int *token_count) { *token_count = 0; + int j; + e_term_sign ret_sign; + + // default to '+' + ret_sign = TERM_PLUS; - // sign if (tokens[i].tag == TOKEN_SIGN) { - *token_count = 1; + // we cna have two signs in a row, like "3 - -2" or "3 - +2" + j = 0; + while (j < 2) + { + if (tokens[i + j].tag != TOKEN_SIGN) + break; + if (tokens[i + j].type == TOKEN_SIGN_MINUS) + ret_sign = (ret_sign == TERM_PLUS) ? TERM_MINUS : TERM_PLUS; + *token_count += 1; + j++; + } } else if (i == 0) { // if most left term, the sign can be ommited for a '+' sign in front of a number or variable *token_count = 0; - return TERM_PLUS; + ret_sign = TERM_PLUS; } else if (tokens[i - 1].type == TOKEN_EQUAL) { // if first token after 'equal', the sign can be ommited for a '+' sign in front of a number or variable *token_count = 0; - return TERM_PLUS; + ret_sign = TERM_PLUS; } else { stop_errors("at begining of term, we should have a token 'sign', not '%s' (token[%i])", token_type_to_str(tokens[i].type), i); } - return tokens[i].type == TOKEN_SIGN_PLUS ? TERM_PLUS : TERM_MINUS; + return ret_sign; } static double get_double_value(s_token token) diff --git a/src/utils/math.c b/src/utils/math.c index 7640bbf..3284282 100644 --- a/src/utils/math.c +++ b/src/utils/math.c @@ -65,7 +65,7 @@ int gcd_int(int a, int b) b = a % b; a = tmp; } - return abs(a); + return ft_abs(a); } // returns the gcd, and modify arguments with new reduced values diff --git a/tester.sh b/tester.sh index 11c109c..cbe0563 100644 --- a/tester.sh +++ b/tester.sh @@ -387,3 +387,67 @@ Polynomial degree: 2 Discriminant is strictly positive, the two solutions are: 1.36992 -1.70326" + +run_test \ +"32. degree 2 sign -" \ +"3x² + -2x -7 = 0" "\ +Reduced form: -7 * x^0 - 2 * x^1 + 3 * x^2 = 0 +Polynomial degree: 2 +Discriminant is strictly positive, the two solutions are: +1.89681 +-1.23014" + +run_test \ +"33. degree 2 float because big" \ +"3x² + 12345678901234567x -7 = 0" "\ +Reduced form: -7 * x^0 + 1.23457e+16 * x^1 + 3 * x^2 = 0 +Polynomial degree: 2 +Discriminant is strictly positive, the two solutions are: +0 +-4.11523e+15" + +run_test \ +"34. degree 2 float because too big by 1" \ +"3x² + 2147483648x -7 = 0" "\ +Reduced form: -7 * x^0 + 2.14748e+09 * x^1 + 3 * x^2 = 0 +Polynomial degree: 2 +Discriminant is strictly positive, the two solutions are: +0 +-7.15828e+08" + +run_test \ +"35. degree 2 float because too small by 1" \ +"3x² + -2147483649x -7 = 0" "\ +Reduced form: -7 * x^0 - 2.14748e+09 * x^1 + 3 * x^2 = 0 +Polynomial degree: 2 +Discriminant is strictly positive, the two solutions are: +7.15828e+08 +0" + +run_test \ +"36. degree 2 int max" \ +"3x² + 2147483647x -7 = 0" "\ +Reduced form: -7 * x^0 + 2.14748e+09 * x^1 + 3 * x^2 = 0 +Polynomial degree: 2 +Discriminant is strictly positive, the two solutions are: +0 +-7.15828e+08" + +run_test \ +"37. degree 2 exponent too big" \ +"3x²¹⁴⁷⁴⁸³⁶⁴⁷ + 2x -7 = 0" \ +"" \ +error + +run_test \ +"38. degree 2 big enough" \ +"3x⁹⁹⁹ + 2x -7 = 0" "\ +Reduced form: -7 * x^0 + 2 * x^1 + 0 * x^2 + 0 * x^3 + 0 * x^4 + 0 * x^5 + 0 * x^6 + 0 * x^7 + 0 * x^8 + 0 * x^9 + 0 * x^10 + 0 * x^11 + 0 * x^12 + 0 * x^13 + 0 * x^14 + 0 * x^15 + 0 * x^16 + 0 * x^17 + 0 * x^18 + 0 * x^19 + 0 * x^20 + 0 * x^21 + 0 * x^22 + 0 * x^23 + 0 * x^24 + 0 * x^25 + 0 * x^26 + 0 * x^27 + 0 * x^28 + 0 * x^29 + 0 * x^30 + 0 * x^31 + 0 * x^32 + 0 * x^33 + 0 * x^34 + 0 * x^35 + 0 * x^36 + 0 * x^37 + 0 * x^38 + 0 * x^39 + 0 * x^40 + 0 * x^41 + 0 * x^42 + 0 * x^43 + 0 * x^44 + 0 * x^45 + 0 * x^46 + 0 * x^47 + 0 * x^48 + 0 * x^49 + 0 * x^50 + 0 * x^51 + 0 * x^52 + 0 * x^53 + 0 * x^54 + 0 * x^55 + 0 * x^56 + 0 * x^57 + 0 * x^58 + 0 * x^59 + 0 * x^60 + 0 * x^61 + 0 * x^62 + 0 * x^63 + 0 * x^64 + 0 * x^65 + 0 * x^66 + 0 * x^67 + 0 * x^68 + 0 * x^69 + 0 * x^70 + 0 * x^71 + 0 * x^72 + 0 * x^73 + 0 * x^74 + 0 * x^75 + 0 * x^76 + 0 * x^77 + 0 * x^78 + 0 * x^79 + 0 * x^80 + 0 * x^81 + 0 * x^82 + 0 * x^83 + 0 * x^84 + 0 * x^85 + 0 * x^86 + 0 * x^87 + 0 * x^88 + 0 * x^89 + 0 * x^90 + 0 * x^91 + 0 * x^92 + 0 * x^93 + 0 * x^94 + 0 * x^95 + 0 * x^96 + 0 * x^97 + 0 * x^98 + 0 * x^99 + 0 * x^100 + 0 * x^101 + 0 * x^102 + 0 * x^103 + 0 * x^104 + 0 * x^105 + 0 * x^106 + 0 * x^107 + 0 * x^108 + 0 * x^109 + 0 * x^110 + 0 * x^111 + 0 * x^112 + 0 * x^113 + 0 * x^114 + 0 * x^115 + 0 * x^116 + 0 * x^117 + 0 * x^118 + 0 * x^119 + 0 * x^120 + 0 * x^121 + 0 * x^122 + 0 * x^123 + 0 * x^124 + 0 * x^125 + 0 * x^126 + 0 * x^127 + 0 * x^128 + 0 * x^129 + 0 * x^130 + 0 * x^131 + 0 * x^132 + 0 * x^133 + 0 * x^134 + 0 * x^135 + 0 * x^136 + 0 * x^137 + 0 * x^138 + 0 * x^139 + 0 * x^140 + 0 * x^141 + 0 * x^142 + 0 * x^143 + 0 * x^144 + 0 * x^145 + 0 * x^146 + 0 * x^147 + 0 * x^148 + 0 * x^149 + 0 * x^150 + 0 * x^151 + 0 * x^152 + 0 * x^153 + 0 * x^154 + 0 * x^155 + 0 * x^156 + 0 * x^157 + 0 * x^158 + 0 * x^159 + 0 * x^160 + 0 * x^161 + 0 * x^162 + 0 * x^163 + 0 * x^164 + 0 * x^165 + 0 * x^166 + 0 * x^167 + 0 * x^168 + 0 * x^169 + 0 * x^170 + 0 * x^171 + 0 * x^172 + 0 * x^173 + 0 * x^174 + 0 * x^175 + 0 * x^176 + 0 * x^177 + 0 * x^178 + 0 * x^179 + 0 * x^180 + 0 * x^181 + 0 * x^182 + 0 * x^183 + 0 * x^184 + 0 * x^185 + 0 * x^186 + 0 * x^187 + 0 * x^188 + 0 * x^189 + 0 * x^190 + 0 * x^191 + 0 * x^192 + 0 * x^193 + 0 * x^194 + 0 * x^195 + 0 * x^196 + 0 * x^197 + 0 * x^198 + 0 * x^199 + 0 * x^200 + 0 * x^201 + 0 * x^202 + 0 * x^203 + 0 * x^204 + 0 * x^205 + 0 * x^206 + 0 * x^207 + 0 * x^208 + 0 * x^209 + 0 * x^210 + 0 * x^211 + 0 * x^212 + 0 * x^213 + 0 * x^214 + 0 * x^215 + 0 * x^216 + 0 * x^217 + 0 * x^218 + 0 * x^219 + 0 * x^220 + 0 * x^221 + 0 * x^222 + 0 * x^223 + 0 * x^224 + 0 * x^225 + 0 * x^226 + 0 * x^227 + 0 * x^228 + 0 * x^229 + 0 * x^230 + 0 * x^231 + 0 * x^232 + 0 * x^233 + 0 * x^234 + 0 * x^235 + 0 * x^236 + 0 * x^237 + 0 * x^238 + 0 * x^239 + 0 * x^240 + 0 * x^241 + 0 * x^242 + 0 * x^243 + 0 * x^244 + 0 * x^245 + 0 * x^246 + 0 * x^247 + 0 * x^248 + 0 * x^249 + 0 * x^250 + 0 * x^251 + 0 * x^252 + 0 * x^253 + 0 * x^254 + 0 * x^255 + 0 * x^256 + 0 * x^257 + 0 * x^258 + 0 * x^259 + 0 * x^260 + 0 * x^261 + 0 * x^262 + 0 * x^263 + 0 * x^264 + 0 * x^265 + 0 * x^266 + 0 * x^267 + 0 * x^268 + 0 * x^269 + 0 * x^270 + 0 * x^271 + 0 * x^272 + 0 * x^273 + 0 * x^274 + 0 * x^275 + 0 * x^276 + 0 * x^277 + 0 * x^278 + 0 * x^279 + 0 * x^280 + 0 * x^281 + 0 * x^282 + 0 * x^283 + 0 * x^284 + 0 * x^285 + 0 * x^286 + 0 * x^287 + 0 * x^288 + 0 * x^289 + 0 * x^290 + 0 * x^291 + 0 * x^292 + 0 * x^293 + 0 * x^294 + 0 * x^295 + 0 * x^296 + 0 * x^297 + 0 * x^298 + 0 * x^299 + 0 * x^300 + 0 * x^301 + 0 * x^302 + 0 * x^303 + 0 * x^304 + 0 * x^305 + 0 * x^306 + 0 * x^307 + 0 * x^308 + 0 * x^309 + 0 * x^310 + 0 * x^311 + 0 * x^312 + 0 * x^313 + 0 * x^314 + 0 * x^315 + 0 * x^316 + 0 * x^317 + 0 * x^318 + 0 * x^319 + 0 * x^320 + 0 * x^321 + 0 * x^322 + 0 * x^323 + 0 * x^324 + 0 * x^325 + 0 * x^326 + 0 * x^327 + 0 * x^328 + 0 * x^329 + 0 * x^330 + 0 * x^331 + 0 * x^332 + 0 * x^333 + 0 * x^334 + 0 * x^335 + 0 * x^336 + 0 * x^337 + 0 * x^338 + 0 * x^339 + 0 * x^340 + 0 * x^341 + 0 * x^342 + 0 * x^343 + 0 * x^344 + 0 * x^345 + 0 * x^346 + 0 * x^347 + 0 * x^348 + 0 * x^349 + 0 * x^350 + 0 * x^351 + 0 * x^352 + 0 * x^353 + 0 * x^354 + 0 * x^355 + 0 * x^356 + 0 * x^357 + 0 * x^358 + 0 * x^359 + 0 * x^360 + 0 * x^361 + 0 * x^362 + 0 * x^363 + 0 * x^364 + 0 * x^365 + 0 * x^366 + 0 * x^367 + 0 * x^368 + 0 * x^369 + 0 * x^370 + 0 * x^371 + 0 * x^372 + 0 * x^373 + 0 * x^374 + 0 * x^375 + 0 * x^376 + 0 * x^377 + 0 * x^378 + 0 * x^379 + 0 * x^380 + 0 * x^381 + 0 * x^382 + 0 * x^383 + 0 * x^384 + 0 * x^385 + 0 * x^386 + 0 * x^387 + 0 * x^388 + 0 * x^389 + 0 * x^390 + 0 * x^391 + 0 * x^392 + 0 * x^393 + 0 * x^394 + 0 * x^395 + 0 * x^396 + 0 * x^397 + 0 * x^398 + 0 * x^399 + 0 * x^400 + 0 * x^401 + 0 * x^402 + 0 * x^403 + 0 * x^404 + 0 * x^405 + 0 * x^406 + 0 * x^407 + 0 * x^408 + 0 * x^409 + 0 * x^410 + 0 * x^411 + 0 * x^412 + 0 * x^413 + 0 * x^414 + 0 * x^415 + 0 * x^416 + 0 * x^417 + 0 * x^418 + 0 * x^419 + 0 * x^420 + 0 * x^421 + 0 * x^422 + 0 * x^423 + 0 * x^424 + 0 * x^425 + 0 * x^426 + 0 * x^427 + 0 * x^428 + 0 * x^429 + 0 * x^430 + 0 * x^431 + 0 * x^432 + 0 * x^433 + 0 * x^434 + 0 * x^435 + 0 * x^436 + 0 * x^437 + 0 * x^438 + 0 * x^439 + 0 * x^440 + 0 * x^441 + 0 * x^442 + 0 * x^443 + 0 * x^444 + 0 * x^445 + 0 * x^446 + 0 * x^447 + 0 * x^448 + 0 * x^449 + 0 * x^450 + 0 * x^451 + 0 * x^452 + 0 * x^453 + 0 * x^454 + 0 * x^455 + 0 * x^456 + 0 * x^457 + 0 * x^458 + 0 * x^459 + 0 * x^460 + 0 * x^461 + 0 * x^462 + 0 * x^463 + 0 * x^464 + 0 * x^465 + 0 * x^466 + 0 * x^467 + 0 * x^468 + 0 * x^469 + 0 * x^470 + 0 * x^471 + 0 * x^472 + 0 * x^473 + 0 * x^474 + 0 * x^475 + 0 * x^476 + 0 * x^477 + 0 * x^478 + 0 * x^479 + 0 * x^480 + 0 * x^481 + 0 * x^482 + 0 * x^483 + 0 * x^484 + 0 * x^485 + 0 * x^486 + 0 * x^487 + 0 * x^488 + 0 * x^489 + 0 * x^490 + 0 * x^491 + 0 * x^492 + 0 * x^493 + 0 * x^494 + 0 * x^495 + 0 * x^496 + 0 * x^497 + 0 * x^498 + 0 * x^499 + 0 * x^500 + 0 * x^501 + 0 * x^502 + 0 * x^503 + 0 * x^504 + 0 * x^505 + 0 * x^506 + 0 * x^507 + 0 * x^508 + 0 * x^509 + 0 * x^510 + 0 * x^511 + 0 * x^512 + 0 * x^513 + 0 * x^514 + 0 * x^515 + 0 * x^516 + 0 * x^517 + 0 * x^518 + 0 * x^519 + 0 * x^520 + 0 * x^521 + 0 * x^522 + 0 * x^523 + 0 * x^524 + 0 * x^525 + 0 * x^526 + 0 * x^527 + 0 * x^528 + 0 * x^529 + 0 * x^530 + 0 * x^531 + 0 * x^532 + 0 * x^533 + 0 * x^534 + 0 * x^535 + 0 * x^536 + 0 * x^537 + 0 * x^538 + 0 * x^539 + 0 * x^540 + 0 * x^541 + 0 * x^542 + 0 * x^543 + 0 * x^544 + 0 * x^545 + 0 * x^546 + 0 * x^547 + 0 * x^548 + 0 * x^549 + 0 * x^550 + 0 * x^551 + 0 * x^552 + 0 * x^553 + 0 * x^554 + 0 * x^555 + 0 * x^556 + 0 * x^557 + 0 * x^558 + 0 * x^559 + 0 * x^560 + 0 * x^561 + 0 * x^562 + 0 * x^563 + 0 * x^564 + 0 * x^565 + 0 * x^566 + 0 * x^567 + 0 * x^568 + 0 * x^569 + 0 * x^570 + 0 * x^571 + 0 * x^572 + 0 * x^573 + 0 * x^574 + 0 * x^575 + 0 * x^576 + 0 * x^577 + 0 * x^578 + 0 * x^579 + 0 * x^580 + 0 * x^581 + 0 * x^582 + 0 * x^583 + 0 * x^584 + 0 * x^585 + 0 * x^586 + 0 * x^587 + 0 * x^588 + 0 * x^589 + 0 * x^590 + 0 * x^591 + 0 * x^592 + 0 * x^593 + 0 * x^594 + 0 * x^595 + 0 * x^596 + 0 * x^597 + 0 * x^598 + 0 * x^599 + 0 * x^600 + 0 * x^601 + 0 * x^602 + 0 * x^603 + 0 * x^604 + 0 * x^605 + 0 * x^606 + 0 * x^607 + 0 * x^608 + 0 * x^609 + 0 * x^610 + 0 * x^611 + 0 * x^612 + 0 * x^613 + 0 * x^614 + 0 * x^615 + 0 * x^616 + 0 * x^617 + 0 * x^618 + 0 * x^619 + 0 * x^620 + 0 * x^621 + 0 * x^622 + 0 * x^623 + 0 * x^624 + 0 * x^625 + 0 * x^626 + 0 * x^627 + 0 * x^628 + 0 * x^629 + 0 * x^630 + 0 * x^631 + 0 * x^632 + 0 * x^633 + 0 * x^634 + 0 * x^635 + 0 * x^636 + 0 * x^637 + 0 * x^638 + 0 * x^639 + 0 * x^640 + 0 * x^641 + 0 * x^642 + 0 * x^643 + 0 * x^644 + 0 * x^645 + 0 * x^646 + 0 * x^647 + 0 * x^648 + 0 * x^649 + 0 * x^650 + 0 * x^651 + 0 * x^652 + 0 * x^653 + 0 * x^654 + 0 * x^655 + 0 * x^656 + 0 * x^657 + 0 * x^658 + 0 * x^659 + 0 * x^660 + 0 * x^661 + 0 * x^662 + 0 * x^663 + 0 * x^664 + 0 * x^665 + 0 * x^666 + 0 * x^667 + 0 * x^668 + 0 * x^669 + 0 * x^670 + 0 * x^671 + 0 * x^672 + 0 * x^673 + 0 * x^674 + 0 * x^675 + 0 * x^676 + 0 * x^677 + 0 * x^678 + 0 * x^679 + 0 * x^680 + 0 * x^681 + 0 * x^682 + 0 * x^683 + 0 * x^684 + 0 * x^685 + 0 * x^686 + 0 * x^687 + 0 * x^688 + 0 * x^689 + 0 * x^690 + 0 * x^691 + 0 * x^692 + 0 * x^693 + 0 * x^694 + 0 * x^695 + 0 * x^696 + 0 * x^697 + 0 * x^698 + 0 * x^699 + 0 * x^700 + 0 * x^701 + 0 * x^702 + 0 * x^703 + 0 * x^704 + 0 * x^705 + 0 * x^706 + 0 * x^707 + 0 * x^708 + 0 * x^709 + 0 * x^710 + 0 * x^711 + 0 * x^712 + 0 * x^713 + 0 * x^714 + 0 * x^715 + 0 * x^716 + 0 * x^717 + 0 * x^718 + 0 * x^719 + 0 * x^720 + 0 * x^721 + 0 * x^722 + 0 * x^723 + 0 * x^724 + 0 * x^725 + 0 * x^726 + 0 * x^727 + 0 * x^728 + 0 * x^729 + 0 * x^730 + 0 * x^731 + 0 * x^732 + 0 * x^733 + 0 * x^734 + 0 * x^735 + 0 * x^736 + 0 * x^737 + 0 * x^738 + 0 * x^739 + 0 * x^740 + 0 * x^741 + 0 * x^742 + 0 * x^743 + 0 * x^744 + 0 * x^745 + 0 * x^746 + 0 * x^747 + 0 * x^748 + 0 * x^749 + 0 * x^750 + 0 * x^751 + 0 * x^752 + 0 * x^753 + 0 * x^754 + 0 * x^755 + 0 * x^756 + 0 * x^757 + 0 * x^758 + 0 * x^759 + 0 * x^760 + 0 * x^761 + 0 * x^762 + 0 * x^763 + 0 * x^764 + 0 * x^765 + 0 * x^766 + 0 * x^767 + 0 * x^768 + 0 * x^769 + 0 * x^770 + 0 * x^771 + 0 * x^772 + 0 * x^773 + 0 * x^774 + 0 * x^775 + 0 * x^776 + 0 * x^777 + 0 * x^778 + 0 * x^779 + 0 * x^780 + 0 * x^781 + 0 * x^782 + 0 * x^783 + 0 * x^784 + 0 * x^785 + 0 * x^786 + 0 * x^787 + 0 * x^788 + 0 * x^789 + 0 * x^790 + 0 * x^791 + 0 * x^792 + 0 * x^793 + 0 * x^794 + 0 * x^795 + 0 * x^796 + 0 * x^797 + 0 * x^798 + 0 * x^799 + 0 * x^800 + 0 * x^801 + 0 * x^802 + 0 * x^803 + 0 * x^804 + 0 * x^805 + 0 * x^806 + 0 * x^807 + 0 * x^808 + 0 * x^809 + 0 * x^810 + 0 * x^811 + 0 * x^812 + 0 * x^813 + 0 * x^814 + 0 * x^815 + 0 * x^816 + 0 * x^817 + 0 * x^818 + 0 * x^819 + 0 * x^820 + 0 * x^821 + 0 * x^822 + 0 * x^823 + 0 * x^824 + 0 * x^825 + 0 * x^826 + 0 * x^827 + 0 * x^828 + 0 * x^829 + 0 * x^830 + 0 * x^831 + 0 * x^832 + 0 * x^833 + 0 * x^834 + 0 * x^835 + 0 * x^836 + 0 * x^837 + 0 * x^838 + 0 * x^839 + 0 * x^840 + 0 * x^841 + 0 * x^842 + 0 * x^843 + 0 * x^844 + 0 * x^845 + 0 * x^846 + 0 * x^847 + 0 * x^848 + 0 * x^849 + 0 * x^850 + 0 * x^851 + 0 * x^852 + 0 * x^853 + 0 * x^854 + 0 * x^855 + 0 * x^856 + 0 * x^857 + 0 * x^858 + 0 * x^859 + 0 * x^860 + 0 * x^861 + 0 * x^862 + 0 * x^863 + 0 * x^864 + 0 * x^865 + 0 * x^866 + 0 * x^867 + 0 * x^868 + 0 * x^869 + 0 * x^870 + 0 * x^871 + 0 * x^872 + 0 * x^873 + 0 * x^874 + 0 * x^875 + 0 * x^876 + 0 * x^877 + 0 * x^878 + 0 * x^879 + 0 * x^880 + 0 * x^881 + 0 * x^882 + 0 * x^883 + 0 * x^884 + 0 * x^885 + 0 * x^886 + 0 * x^887 + 0 * x^888 + 0 * x^889 + 0 * x^890 + 0 * x^891 + 0 * x^892 + 0 * x^893 + 0 * x^894 + 0 * x^895 + 0 * x^896 + 0 * x^897 + 0 * x^898 + 0 * x^899 + 0 * x^900 + 0 * x^901 + 0 * x^902 + 0 * x^903 + 0 * x^904 + 0 * x^905 + 0 * x^906 + 0 * x^907 + 0 * x^908 + 0 * x^909 + 0 * x^910 + 0 * x^911 + 0 * x^912 + 0 * x^913 + 0 * x^914 + 0 * x^915 + 0 * x^916 + 0 * x^917 + 0 * x^918 + 0 * x^919 + 0 * x^920 + 0 * x^921 + 0 * x^922 + 0 * x^923 + 0 * x^924 + 0 * x^925 + 0 * x^926 + 0 * x^927 + 0 * x^928 + 0 * x^929 + 0 * x^930 + 0 * x^931 + 0 * x^932 + 0 * x^933 + 0 * x^934 + 0 * x^935 + 0 * x^936 + 0 * x^937 + 0 * x^938 + 0 * x^939 + 0 * x^940 + 0 * x^941 + 0 * x^942 + 0 * x^943 + 0 * x^944 + 0 * x^945 + 0 * x^946 + 0 * x^947 + 0 * x^948 + 0 * x^949 + 0 * x^950 + 0 * x^951 + 0 * x^952 + 0 * x^953 + 0 * x^954 + 0 * x^955 + 0 * x^956 + 0 * x^957 + 0 * x^958 + 0 * x^959 + 0 * x^960 + 0 * x^961 + 0 * x^962 + 0 * x^963 + 0 * x^964 + 0 * x^965 + 0 * x^966 + 0 * x^967 + 0 * x^968 + 0 * x^969 + 0 * x^970 + 0 * x^971 + 0 * x^972 + 0 * x^973 + 0 * x^974 + 0 * x^975 + 0 * x^976 + 0 * x^977 + 0 * x^978 + 0 * x^979 + 0 * x^980 + 0 * x^981 + 0 * x^982 + 0 * x^983 + 0 * x^984 + 0 * x^985 + 0 * x^986 + 0 * x^987 + 0 * x^988 + 0 * x^989 + 0 * x^990 + 0 * x^991 + 0 * x^992 + 0 * x^993 + 0 * x^994 + 0 * x^995 + 0 * x^996 + 0 * x^997 + 0 * x^998 + 3 * x^999 = 0 +Polynomial degree: 999 +The polynomial degree is strictly greater than 2, I can't solve." + +run_test \ +"39. degree 2 too big by one" \ +"3x¹⁰⁰⁰ + 2x -7 = 0" \ +"" \ +error