From a62dd411aa4e3f16eb679a2bc8af6a7e25b38f00 Mon Sep 17 00:00:00 2001 From: Matthieu Bessat Date: Sat, 30 Apr 2022 16:16:37 +0200 Subject: [PATCH] feat(Evaluator): add pow operator feat(Evaluator): add minus sign reducing fix(Evaluator): trim spaces test: add base for unit testing --- .gitignore | 1 + Makefile | 8 +- src/evaluator.c | 212 ++++++++++++++++++++++++--------- src/evaluator.h | 2 +- src/funcs.c | 23 ++-- src/list.c | 9 ++ src/list.h | 2 + src/main.c | 2 +- src/number_parsing.c | 28 +---- src/operate.c | 12 +- src/repr_utils.c | 23 ---- src/repr_utils.h | 10 -- src/utils.c | 255 ++++++++++++++++++++++++++++++++++++++++ src/utils.h | 38 ++++++ test.c | 29 +++-- tests/test.c | 10 ++ tests/test_evaluation.c | 60 ++++++++++ tests/test_evaluation.h | 1 + tests/test_utils.c | 65 ++++++++++ tests/test_utils.h | 1 + 20 files changed, 654 insertions(+), 137 deletions(-) delete mode 100644 src/repr_utils.c delete mode 100644 src/repr_utils.h create mode 100644 src/utils.c create mode 100644 src/utils.h create mode 100644 tests/test.c create mode 100644 tests/test_evaluation.c create mode 100644 tests/test_evaluation.h create mode 100644 tests/test_utils.c create mode 100644 tests/test_utils.h diff --git a/.gitignore b/.gitignore index f29cd6b..047802d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ ./main ./test main +bin/* diff --git a/Makefile b/Makefile index ad9abfa..3d3f42d 100644 --- a/Makefile +++ b/Makefile @@ -2,5 +2,11 @@ WERROR?= CFLAGS=-Wall -Wextra $(WERROR) -pedantic -I. CXXFLAGS_WITHOUT_PKGS=$(CFLAGS) -fno-exceptions -Wno-missing-braces -Wswitch-enum -lm +TEST_SRCS_ENC := $(foreach DIR,src,$(patsubst $(DIR)/%,%,$(wildcard ./src/*.c))) +TEST_SRCS_ENC := $(filter-out %main.c, $(TEST_SRCS_ENC)) + build: - gcc src/* -o ./main ${CXXFLAGS_WITHOUT_PKGS} + gcc src/* -o ./bin/main ${CXXFLAGS_WITHOUT_PKGS} +test: + gcc ${TEST_SRCS_ENC} ./tests/* -o ./bin/test ${CXXFLAGS_WITHOUT_PKGS} + ./bin/test diff --git a/src/evaluator.c b/src/evaluator.c index c7172e0..713c1f5 100644 --- a/src/evaluator.c +++ b/src/evaluator.c @@ -69,6 +69,59 @@ int evaluator_reduce_operator_pattern(struct List* evalList) { return 0; } +/** +This sub script will look for pattern like Operator (minus sign) Number +and evaluate that +*/ +int evaluator_reduce_minus_pattern(struct List* evalList) { + int patternPos = -1; + for (int i = 0; i < evalList->num_elements; i++) { + if ( + ((i >= 1 && !is_type_number(list_get_type(evalList, i-1))) || (i == 0)) && + list_get_type(evalList, i) == TYPE_OPERATOR && + is_type_number(list_get_type(evalList, i+1)) + ) { + char candidateOperator; + list_get(evalList, i, &candidateOperator); + if (candidateOperator != '-') { + continue; + } + + patternPos = i; + break; + } + } + + if (patternPos == -1) { + // we did not find anything to reduce we return negative + return -1; + } + // we found a positive pattern, we gonna reduce + int type = list_get_type(evalList, patternPos+1); + int val; + list_get(evalList, patternPos+1, &val); + + int res = 0; + unsigned char typeRes = 0; + int operateStatus = operate('*', TYPE_INT, -1, type, val, &typeRes, &res); + if (operateStatus != 0) { + printf("ERR Evaluator: cannot operate \n"); + return 400; + } + + if (typeRes == TYPE_INT) { + list_set(evalList, patternPos, TYPE_INT, &res); + } + if (typeRes == TYPE_FLOAT) { + // FIXME: invalid type set, we need to flag for float + list_set(evalList, patternPos, TYPE_FLOAT, &res); + } + + list_delete(evalList, patternPos+1); + + return 0; +} + /** This sub script will look for pattern like ({Number}) @@ -78,6 +131,7 @@ int evaluator_reduce_parenthesis_pattern(struct List* evalList) { int patternPos = -1; for (int i = 0; i < evalList->num_elements; i++) { if ( + ((i >= 1 && list_get_type(evalList, i-1) != TYPE_FUNC_NAME) || (i == 0)) && list_get_type(evalList, i) == TYPE_OPEN_PARENTHESIS && is_type_number(list_get_type(evalList, i+1)) && list_get_type(evalList, i+2) == TYPE_CLOSE_PARENTHESIS @@ -118,26 +172,13 @@ if we don't find that, we throw an error int evaluator_reduce_function_call(struct List* evalList) { int patternPos = -1; - short argsLen = 0; for (int i = 0; i < evalList->num_elements; i++) { - if ( - (list_get_type(evalList, i) == TYPE_FUNC_NAME && - list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS && - is_type_number(list_get_type(evalList, i+2))) - ) { - // mode: we have at least one argument - patternPos = i; - argsLen = 1; - break; - } if ( list_get_type(evalList, i) == TYPE_FUNC_NAME && - list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS && - list_get_type(evalList, i+2) == TYPE_CLOSE_PARENTHESIS + list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS ) { - // special mode: functions call with no arguments + // mode: we have a function call patternPos = i; - argsLen = 0; break; } } @@ -151,39 +192,54 @@ int evaluator_reduce_function_call(struct List* evalList) { // fetch the function ID list_get(evalList, patternPos, &funcID); + short argsLen = 0; int pos = patternPos+2; - if (argsLen > 0) { - // now we know we have a start of a function - // we gonna start to look if there is others arguments - // two case: either we have another arguments or we have a closing parenthesis - pos = patternPos+3; - while (1) { - if (argsLen > 16) { - printf("ERR Evaluator: too many arguments passed to func \n"); - return 100; - } - if ( - list_get_type(evalList, pos) == TYPE_COMMA && - is_type_number(list_get_type(evalList, pos+1)) - ) { - // another argument - pos += 2; - argsLen++; - continue; - } - if ( - ( - list_get_type(evalList, pos) == TYPE_COMMA && - list_get_type(evalList, pos+1) == TYPE_CLOSE_PARENTHESIS - ) || (list_get_type(evalList, pos) == TYPE_CLOSE_PARENTHESIS) - ) { - // we close the function call - break; - } - printf("ERR Evaluator: cannot reduce function call \n"); + // now we know we have a start of a function + // we gonna start to look if there is others arguments + // two case: either we have another arguments or we have a closing parenthesis + while (1) { + if (argsLen > 16) { + printf("ERR Evaluator: too many arguments passed to func (max out the limit) \n"); return 100; } + if ( + list_get_type(evalList, pos) == TYPE_CLOSE_PARENTHESIS + ) { + // end of the function call + pos += 0; + break; + } + if ( + list_get_type(evalList, pos) == TYPE_COMMA && + list_get_type(evalList, pos+1) == TYPE_CLOSE_PARENTHESIS + ) { + // end of the function call + pos += 1; + break; + } + + if ( + is_type_number(list_get_type(evalList, pos)) && + list_get_type(evalList, pos+1) == TYPE_COMMA + ) { + // this is a new argument + pos += 2; + argsLen++; + continue; + } + if ( + is_type_number(list_get_type(evalList, pos)) && + list_get_type(evalList, pos+1) == TYPE_CLOSE_PARENTHESIS + ) { + // we didn't match the last pattern so it's the last argument + pos += 1; + argsLen++; + continue; + } + + // we cannot reduce more, it's probably because the func call is not ready to be reduced, meaning that the arguments need to be evaluated + return -1; } // now pos is the index of the last component for this func call @@ -209,13 +265,18 @@ int evaluator_reduce_function_call(struct List* evalList) { // now we can delete in the list from pos+1 patternPos to pos // just delete N-1 times where N is the number of components in the func call //printf("start: %d, end: %d \n", patternPos, pos); - + //printf("patternPos: %d, pos: %d \n", patternPos, pos); for (int j = 0; j < (pos-patternPos); j++) { list_delete(evalList, patternPos); } + //printf("list report after deleting after applying a func \n"); + //list_print(evalList); + + //printf("patternPos: %d, resType: %d \n", patternPos, resType); list_set(evalList, patternPos, resType, &resVal); + return 0; } @@ -226,7 +287,7 @@ Arguments: - Input String: char pointer (the source of the evaluation) - Result: int pointer (where the result of the evaluation will be written) */ -int evaluate(char* inputStr, int* resultPtr, int* typePtr) { +int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) { int i = 0; int _len = strlen(inputStr); // we want first to parse the expression and create a stack @@ -315,19 +376,55 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) { } struct List evalList; + // NOTICE: for some reason the struct don't reset after a usage + list_reset(&evalList); printf("\n - constructing list \n"); // initializing the evaluation list for (int j = 0; j < partitionPtr; j++) { - int len = partitionStopPos[j] - partitionStartPos[j]; + + int startPos = partitionStartPos[j]; + int stopPos = partitionStopPos[j]; + printf("=== %d\n", j); + printf("startPos %d, stopPos %d\n", startPos, stopPos); + int len = stopPos - startPos; + + // modifiy the start and stop pos to trim spaces + int startTrimOffset = 0; + int stopTrimOffset = 0; + for (int z = 0; z < len; z++) { + if (inputStr[startPos+z] != ' ') { + break; + } + startTrimOffset++; + } + for (int z = 1; z < len; z++) { + if (inputStr[stopPos-z] != ' ') { + break; + } + stopTrimOffset++; + } + startPos += startTrimOffset; + stopPos -= stopTrimOffset; + + len = stopPos - startPos; char buff[_len+1]; + buff[0] = 0; + // fill the buffer with the component string for (int z = 0; z < len; z++) { - buff[z] = inputStr[partitionStartPos[j]+z]; + buff[z] = inputStr[startPos+z]; } + buff[len] = 0; // terminate the buff // TODO: SPLIT INTO A FUNCTION "identify_token(char* str)" - buff[len] = 0; + + printf("buff: '%s' \n", buff); + char dumbValue = (char) 0; + + if (buff[0] == '\0') { + continue; + } if (len == 1 && buff[0] == '(') { list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue); continue; @@ -341,11 +438,12 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) { continue; } if (len == 1 && is_operator(buff[0])) { + printf("found op\n"); char opValue = buff[0]; list_set(&evalList, evalList.num_elements, TYPE_OPERATOR, &opValue); continue; } - + int res = 0; int st = parse_int(buff, &res); if (st == 0) { @@ -374,6 +472,7 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) { list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID); } } + printf("end of l\n"); } // check the content of this thing @@ -383,10 +482,10 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) { while (evalList.num_elements > 1) { list_print(&evalList); - // we are going to look for pattern - // - 0. OPENP NUM CLOSEP - // - 1. NUM OP NUM + // we are going to look for pattern to reduce + // the order is really important here int reduceFuncOpStat = evaluator_reduce_function_call(&evalList); + int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList); int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList); int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList); @@ -401,7 +500,12 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) { return reduceOperatorOpStat; } - if (reduceFuncOpStat == -1 && reduceOperatorOpStat == -1 && reduceParenthesisOpStat == -1) { + if ( + reduceFuncOpStat == -1 && + reduceOperatorOpStat == -1 && + reduceParenthesisOpStat == -1 && + reduceMinusOpStat == -1 + ) { // all scans failed to find things to reduce // this is actually a failure because we can't do anything to get down to 1 element in the eval list printf("ERR Evaluator: could not reduce more, dumping evalList: \n"); diff --git a/src/evaluator.h b/src/evaluator.h index 9356b0b..0e41e9a 100644 --- a/src/evaluator.h +++ b/src/evaluator.h @@ -1,6 +1,6 @@ #ifndef EVALUATOR_H_ #define EVALUATOR_H_ -int evaluate(char* inputStr, int* resultPtr, int* typePtr); +int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr); #endif diff --git a/src/funcs.c b/src/funcs.c index 21f06d3..52144d9 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -2,16 +2,15 @@ #include #include #include "./types.h" -#include "./repr_utils.h" +#include "./utils.h" int abs_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) { if (types[0] == TYPE_INT) { + *res = args[0]; if (args[0] < 0) { *res = -args[0]; - return 0; } - *res = args[0]; *resType = TYPE_INT; return 0; } @@ -73,7 +72,7 @@ int max_implementation(int* res, unsigned char* resType, unsigned char* types, i int get_pi_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) { - float val = 3.1415926535; + float val = CST_PI; *res = *(int *)(&val); *resType = TYPE_FLOAT; return 0; @@ -88,10 +87,10 @@ struct FuncIntro { // void* are actually long! struct FuncIntro intros[] = { - {"ABS", &abs_implementation, 1}, - {"SQRT", &sqrt_implementation, 1}, - {"MAX", &max_implementation, 2}, - {"GET_PI", &get_pi_implementation, 0}, + {"abs", &abs_implementation, 1}, + {"sqrt", &sqrt_implementation, 1}, + {"max", &max_implementation, 2}, + {"get_pi", &get_pi_implementation, 0}, {"", 0, 0} }; @@ -135,7 +134,13 @@ int execute_func(short funcID, short argsLen, unsigned char* argsTypes, int* arg // call the function implementation // first cast the function ptr impl(resPtr, resTypePtr, argsTypes, argsValues); - printf("Got %d \n", *resPtr); + if (*resTypePtr == TYPE_FLOAT) { + printf("Got TYPE_FLOAT with val: %f \n", get_float_from_int_rep(*resPtr)); + } else if (*resTypePtr == TYPE_INT) { + printf("Got TYPE_INT with val: %d \n", *resPtr); + } else { + printf("Got WTF NOTHING (%d) with val: %d \n", *resTypePtr, *resPtr); + } return 0; } diff --git a/src/list.c b/src/list.c index 65e92ca..b8d1b31 100644 --- a/src/list.c +++ b/src/list.c @@ -194,6 +194,15 @@ int list_delete(struct List* list, int index) return 0; } +void list_reset(struct List* list) +{ + for (int i = 0; i < list->num_elements; i++) { + list_delete(list, 0); + } + list->data_ptr = 0; + list->bytes_used = 0; + list->num_elements = 0; +} int list_append_int(struct List* list, int value) { diff --git a/src/list.h b/src/list.h index f34d23d..6e06070 100644 --- a/src/list.h +++ b/src/list.h @@ -68,4 +68,6 @@ int list_delete(struct List* list, int index); void list_print(struct List*); +void list_reset(struct List* list); + #endif diff --git a/src/main.c b/src/main.c index bb195ab..951bbdf 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ #include "./list.h" #include "./number_parsing.h" #include "./evaluator.h" -#include "./repr_utils.h" +#include "./utils.h" #include "./types.h" //int create_stack(int a, int b) diff --git a/src/number_parsing.c b/src/number_parsing.c index fd047cd..13fd306 100644 --- a/src/number_parsing.c +++ b/src/number_parsing.c @@ -1,29 +1,7 @@ #include #include #include "./number_parsing.h" - -int is_char_numeral(char candidate) { - int n = (int) candidate; - return (n >= 48 && n <= 57); -} - -int integer_pow(int base, int exponent) -{ - if (exponent == 0) return 1; - int r = 1; - int multiplier = base; - while (exponent) { - // if exponent is even - if (exponent & 1) { - r *= multiplier; - } - - multiplier *= multiplier; - exponent >>= 1; // divide by two the exponent - } - - return r; -} +#include "./utils.h" int parse_clean_positive_integer(int inputStrLen, char* inputStr, int* result) { /** @@ -152,8 +130,8 @@ int parse_float(char* inputStr, float* resultPtr) { } cleanStrIntPart[cleanStrIntPartLen] = 0; cleanStrFloatPart[cleanStrFloatPartLen] = 0; - printf("clean str int part: /%s/ \n", cleanStrIntPart); - printf("clean str float part: /%s/ \n", cleanStrFloatPart); + // printf("clean str int part: /%s/ \n", cleanStrIntPart); + // printf("clean str float part: /%s/ \n", cleanStrFloatPart); int intPart = 0; parse_clean_positive_integer(cleanStrIntPartLen, cleanStrIntPart, &intPart); diff --git a/src/operate.c b/src/operate.c index 6b9368c..5dc34f0 100644 --- a/src/operate.c +++ b/src/operate.c @@ -1,14 +1,16 @@ -#include "./operate.h" -#include "./types.h" #include #include +#include "./operate.h" +#include "./types.h" +#include "./utils.h" int is_operator(char candidate) { return ( candidate == '*' || candidate == '/' || candidate == '+' || - candidate == '-' + candidate == '-' || + candidate == '^' ); } @@ -49,6 +51,8 @@ int operate( res = a*b; } else if (operator == '/') { res = a/b; + } else if (operator == '^') { + res = 0; } else { return 2; } @@ -67,6 +71,8 @@ int operate( res = aRepr-bRepr; } else if (operator == '*') { res = aRepr*bRepr; + } else if (operator == '^') { + res = integer_pow(aRepr, bRepr); } else { return 2; } diff --git a/src/repr_utils.c b/src/repr_utils.c deleted file mode 100644 index 821beb4..0000000 --- a/src/repr_utils.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "./repr_utils.h" - -int get_int_rep_from_float(float ft) -{ - return *(int *)(&ft); -} - -/** - * Get a single precision floating point from int representation - * (following IEEE 754) - */ -float get_float_from_int_rep(int representation) -{ - float res; - *((int*) &res) = representation; - - return res; -} - -int get_int_rep_from_char(char c) -{ - return *(int *)(&c); -} diff --git a/src/repr_utils.h b/src/repr_utils.h deleted file mode 100644 index 24e84cf..0000000 --- a/src/repr_utils.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef REPR_UTILS_H_ -#define REPR_UTILS_H_ - -int get_int_rep_from_float(float ft); - -float get_float_from_int_rep(int representation); - -int get_int_rep_from_char(char c); - -#endif diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..76f4a90 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,255 @@ +#include +#include "./utils.h" + +int get_int_rep_from_float(float ft) +{ + return *(int *)(&ft); +} + +/** + * Get a single precision floating point from int representation + * (following IEEE 754) + */ +float get_float_from_int_rep(int representation) +{ + float res; + *((int*) &res) = representation; + + return res; +} + +int get_int_rep_from_char(char c) +{ + return *(int *)(&c); +} + +int is_char_numeral(char candidate) +{ + int n = (int) candidate; + return (n >= 48 && n <= 57); +} + +int float_almost_equal(float a, float b) +{ + float diff = a-b; + if (diff < 0) diff = -diff; + + return diff < 0.001; +} + +int abs_int(int a) +{ + return a < 0 ? -a : a; +} + +float abs_float(float a) +{ + return a < 0 ? -a : a; +} + +int integer_pow(int base, int exponent) +{ + if (exponent == 0) return 1; + int r = 1; + int multiplier = base; + while (exponent) { + // if exponent is even + if (exponent & 1) { + r *= multiplier; + } + + multiplier *= multiplier; + exponent >>= 1; // divide by two the exponent + } + + return r; +} + +float m_float_pow(float base, int exponent) +{ + if (exponent == 0) return 1; + float r = 1; + float multiplier = base; + while (exponent) { + // if exponent is even + if (exponent & 1) { + r *= multiplier; + } + + multiplier *= multiplier; + exponent >>= 1; // divide by two the exponent + } + + return r; +} + +int m_factorial(int x) +{ + if (x == 0 || x == 1) { + return 1; + } + int res = 1; + for (int i = 2; i < x+1; i++) { + res *= i; + } + return res; +} + +float m_exp(float x) +{ + const int n = 10; + float out = 0; + for (int i = 0; i < n; i++) { + out += m_float_pow(x, i)/m_factorial(i); + } + return out; +} + +float m_float_mod(float a, float b) +{ + float mod; + // Handling negative values + if (a < 0) + mod = -a; + else + mod = a; + if (b < 0) + b = -b; + + // Finding mod by repeated subtraction + + while (mod >= b) + mod = mod - b; + + // Sign of result typically depends + // on sign of a. + if (a < 0) + return -mod; + + return mod; +} + +float m_sin(float originalX) +{ + // use cycles in expension series + if (originalX > 2*CST_PI) { + originalX = m_float_mod(originalX, (float) (2*CST_PI)); + } + float x = originalX; + + if (originalX > CST_PI) { + x -= CST_PI; + } + + const int n = 6; + float out = 0; + + int sign = 1; + for (int i = 0; i < n; i++) { + out += sign*(m_float_pow(x, 2*i+1)/m_factorial(2*i+1)); + + if (sign == 1) { + sign = -1; + } else { + sign = 1; + } + } + + if (originalX > CST_PI) { + return -out; + } + return out; +} + +float m_cos(float x) +{ + return m_sin(x+2*CST_PI); +} + +float m_tan(float x) +{ + return m_sin(x)/m_cos(x); +} + +// float m_get_derivative(float (*func)(float), float a) +// { +// float h = 0.0001; +// return ((func(a+h)-func(a))/h); +// } + +// euler method in one dimension +// takes a function and find one of the root +// return the status 0 if success >0 if error +int m_euler_method(float (*func)(float, float), float param, float startsAt, float* resPtr) +{ + // (x-b)f'(b)+f(b) = 0 + // xf'(b)-bf'(b)+f(b) = 0 + // x = (-f(b)+bf'(b))/f'(b) + + float cursor = startsAt; + float newCursor = 0; + float derivative = 0; + short runs = 0; + const float h = 0.0001; + while (1) + { + derivative = (func(param, cursor+h)-func(param, cursor))/h; + newCursor = cursor - func(param, cursor)/derivative; + if (abs_float(cursor - newCursor) < 0.0001) { + *resPtr = (cursor + newCursor)/2; + return 0; + } + if (runs > 100) { + printf("ERR: euler methods failed, coup dur pour euler \n"); + return 100; + } + cursor = newCursor; + runs++; + } + + return 101; +} + +float m_sqrt_equation(float x, float y) +{ + return m_float_pow(y,2)-x; +} + +float m_sqrt(float x) +{ + float res = 0; + m_euler_method(&m_sqrt_equation, x, 4, &res); + + return res; +} + +float m_ln_equation(float x, float y) +{ + return m_exp(y)-x; +} + +float m_ln(float x) +{ + float res = 0; + m_euler_method(&m_ln_equation, x, 4, &res); + + return res; +} + +int is_full_of_space(char* str) +{ + int i = 0; + while (str[i] != '\0') { + if (str[i] != ' ') { + return 0; + } + i++; + } + return 1; +} + +char* trim_space(char* str) +{ + // TODO: implements me + return str; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..05e0767 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,38 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +#define CST_PI 3.1415926535 + +int get_int_rep_from_float(float ft); + +float get_float_from_int_rep(int representation); + +int get_int_rep_from_char(char c); + +int is_char_numeral(char candidate); + +int integer_pow(int base, int exponent); + +int float_almost_equal(float a, float b); + +int m_factorial(int x); + +float m_float_pow(float base, int exponent); + +float m_sqrt(float x); + +float m_exp(float x); + +float m_ln(float x); + +float m_sin(float x); + +float m_cos(float x); + +float m_tan(float x); + +int is_full_of_space(char* str); + +char* trim_space(char* str); + +#endif diff --git a/test.c b/test.c index d60a77b..9fdb52b 100644 --- a/test.c +++ b/test.c @@ -3,7 +3,7 @@ #include "./src/list.h" #include "./src/number_parsing.h" #include "./src/funcs.h" -#include "./src/repr_utils.h" +#include "./src/utils.h" int some_computation(int a, int b, int* resPtr) { @@ -11,7 +11,16 @@ int some_computation(int a, int b, int* resPtr) return 0; } +float test_func(float x) +{ + return m_float_pow(x,2)-2; +} + int main () { + // test of euler + printf("lel : %f \n", m_sqrt(64)); + + // struct List l1; // list_append_int(&l1, 4); @@ -33,16 +42,16 @@ int main () { // void* ptr = &res; // printf("%d\n", sizeof(ptr)); - int found = identify_func_name("ABS"); - printf("found: %d \n", found); + // int found = identify_func_name("ABS"); + // printf("found: %d \n", found); - unsigned char argsType[1] = { TYPE_FLOAT }; - int argsVals[1] = { get_int_rep_from_float(-3.145) }; - int resVal = 0; - unsigned char resType = 0; - execute_func(found, 1, argsType, argsVals, &resVal, &resType); - printf("func res type: %d \n", resType); - printf("func res: %f \n", get_float_from_int_rep(resVal)); + // unsigned char argsType[1] = { TYPE_FLOAT }; + // int argsVals[1] = { get_int_rep_from_float(-3.145) }; + // int resVal = 0; + // unsigned char resType = 0; + // execute_func(found, 1, argsType, argsVals, &resVal, &resType); + // printf("func res type: %d \n", resType); + // printf("func res: %f \n", get_float_from_int_rep(resVal)); // int stat = parse_float("1052.254", &res); // printf("float parsing stat: %d \n", stat); diff --git a/tests/test.c b/tests/test.c new file mode 100644 index 0000000..971cd98 --- /dev/null +++ b/tests/test.c @@ -0,0 +1,10 @@ +#include "./test_utils.h" +#include "./test_evaluation.h" +#include + +int main() +{ + printf("== UNIT TESTS == \n"); + test_utils(); + test_evaluation(); +} diff --git a/tests/test_evaluation.c b/tests/test_evaluation.c new file mode 100644 index 0000000..ca07a90 --- /dev/null +++ b/tests/test_evaluation.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include "../src/types.h" +#include "../src/number_parsing.h" +#include "../src/utils.h" +#include "../src/evaluator.h" + +void test_evaluation() +{ + printf("== test evaluation == \n"); + + // test int parsing + int resVal = 0; + unsigned char resType = 0; + + evaluate("-4", &resVal, &resType); + assert(resType == TYPE_INT); + assert(-4 == resVal); + + evaluate("-(4+9)+1", &resVal, &resType); + assert(resType == TYPE_INT); + assert(-12 == resVal); + + evaluate("(-(8-9+5))+8", &resVal, &resType); + assert(resType == TYPE_INT); + assert(4 == resVal); + + evaluate("2^6", &resVal, &resType); + assert(resType == TYPE_INT); + assert(64 == resVal); + + evaluate("3 + 4", &resVal, &resType); + assert(resType == TYPE_INT); + assert(7 == resVal); + + evaluate("(2*4)+0+0", &resVal, &resType); + assert(resType == TYPE_INT); + assert(8 == resVal); + + evaluate("2.5-(2+0.1)", &resVal, &resType); + assert(resType == TYPE_FLOAT); + assert(float_almost_equal(0.4, get_float_from_int_rep(resVal))); + + evaluate("1^0 + (7*(5 +2))", &resVal, &resType); + assert(resType == TYPE_INT); + assert(50 == resVal); + + evaluate("- ( 0.1+ 0.3 )", &resVal, &resType); + assert(resType == TYPE_FLOAT); + assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal))); + + evaluate("sqrt(2)-1", &resVal, &resType); + assert(resType == TYPE_FLOAT); + assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal))); + + evaluate("(abs((0-1)*2)) + abs(2)", &resVal, &resType); + assert(resType == TYPE_INT); + assert(4 == resVal); +} \ No newline at end of file diff --git a/tests/test_evaluation.h b/tests/test_evaluation.h new file mode 100644 index 0000000..5aee13c --- /dev/null +++ b/tests/test_evaluation.h @@ -0,0 +1 @@ +void test_evaluation(); diff --git a/tests/test_utils.c b/tests/test_utils.c new file mode 100644 index 0000000..7813538 --- /dev/null +++ b/tests/test_utils.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include "../src/number_parsing.h" +#include "../src/utils.h" + +void test_utils() +{ + printf("== test utils == \n"); + + // test int parsing + char test1[] = "151087"; + int res = 0; + parse_clean_positive_integer(strlen(test1), test1, &res); + assert(res == 151087); + + char test2[] = "-428579"; + parse_int(test2, &res); + assert(res == -428579); + + + float res3 = 0; + char test3[] = "3121.897"; + parse_float(test3, &res3); + assert(float_almost_equal(3121.897, res3)); + + float res4 = 0; + char test4[] = "-0.4397"; + parse_float(test4, &res4); + assert(float_almost_equal(-0.4397, res4)); + + assert(integer_pow(1, 0) == 1); + assert(integer_pow(2, 1) == 2); + assert(integer_pow(2, 6) == 64); + + assert(m_factorial(0) == 1); + assert(m_factorial(1) == 1); + assert(m_factorial(2) == 2); + assert(m_factorial(3) == 6); + assert(m_factorial(4) == 2*3*4); + + assert(float_almost_equal(2.7182, m_exp(1.0))); + assert(float_almost_equal(1, m_exp(0))); + + assert(float_almost_equal(0, m_sin(0))); + assert(float_almost_equal(1, m_sin(CST_PI/2))); + assert(float_almost_equal(0, m_sin(CST_PI))); + assert(float_almost_equal(-1, m_sin(3*CST_PI/2))); + assert(float_almost_equal(0, m_sin(2*CST_PI))); + assert(float_almost_equal(0, m_sin(4*CST_PI))); + + assert(float_almost_equal(1.41421, m_sqrt(2))); + assert(float_almost_equal(2.2360, m_sqrt(5))); + + assert(float_almost_equal(0, m_ln(1))); + assert(float_almost_equal(1, m_ln(2.7182818))); + + // char src[] = " hello world "; + // char* trimed = trim_space(src); + // assert(strcmp("hello world", trimed) == 0); + + // char src2[] = "hello"; + // char* trimed2 = trim_space(&src2); + // assert(strcmp("hello", trimed2) == 0); +} \ No newline at end of file diff --git a/tests/test_utils.h b/tests/test_utils.h new file mode 100644 index 0000000..70de024 --- /dev/null +++ b/tests/test_utils.h @@ -0,0 +1 @@ +void test_utils();