feat(Evaluator): add pow operator
feat(Evaluator): add minus sign reducing fix(Evaluator): trim spaces test: add base for unit testing
This commit is contained in:
parent
17c7c247af
commit
a62dd411aa
20 changed files with 654 additions and 137 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
./main
|
./main
|
||||||
./test
|
./test
|
||||||
main
|
main
|
||||||
|
bin/*
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -2,5 +2,11 @@ WERROR?=
|
||||||
CFLAGS=-Wall -Wextra $(WERROR) -pedantic -I.
|
CFLAGS=-Wall -Wextra $(WERROR) -pedantic -I.
|
||||||
CXXFLAGS_WITHOUT_PKGS=$(CFLAGS) -fno-exceptions -Wno-missing-braces -Wswitch-enum -lm
|
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:
|
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
|
||||||
|
|
212
src/evaluator.c
212
src/evaluator.c
|
@ -69,6 +69,59 @@ int evaluator_reduce_operator_pattern(struct List* evalList) {
|
||||||
return 0;
|
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})
|
This sub script will look for pattern like ({Number})
|
||||||
|
@ -78,6 +131,7 @@ int evaluator_reduce_parenthesis_pattern(struct List* evalList) {
|
||||||
int patternPos = -1;
|
int patternPos = -1;
|
||||||
for (int i = 0; i < evalList->num_elements; i++) {
|
for (int i = 0; i < evalList->num_elements; i++) {
|
||||||
if (
|
if (
|
||||||
|
((i >= 1 && list_get_type(evalList, i-1) != TYPE_FUNC_NAME) || (i == 0)) &&
|
||||||
list_get_type(evalList, i) == TYPE_OPEN_PARENTHESIS &&
|
list_get_type(evalList, i) == TYPE_OPEN_PARENTHESIS &&
|
||||||
is_type_number(list_get_type(evalList, i+1)) &&
|
is_type_number(list_get_type(evalList, i+1)) &&
|
||||||
list_get_type(evalList, i+2) == TYPE_CLOSE_PARENTHESIS
|
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 evaluator_reduce_function_call(struct List* evalList) {
|
||||||
int patternPos = -1;
|
int patternPos = -1;
|
||||||
|
|
||||||
short argsLen = 0;
|
|
||||||
for (int i = 0; i < evalList->num_elements; i++) {
|
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 (
|
if (
|
||||||
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
||||||
list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS &&
|
list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS
|
||||||
list_get_type(evalList, i+2) == TYPE_CLOSE_PARENTHESIS
|
|
||||||
) {
|
) {
|
||||||
// special mode: functions call with no arguments
|
// mode: we have a function call
|
||||||
patternPos = i;
|
patternPos = i;
|
||||||
argsLen = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,39 +192,54 @@ int evaluator_reduce_function_call(struct List* evalList) {
|
||||||
// fetch the function ID
|
// fetch the function ID
|
||||||
list_get(evalList, patternPos, &funcID);
|
list_get(evalList, patternPos, &funcID);
|
||||||
|
|
||||||
|
short argsLen = 0;
|
||||||
int pos = patternPos+2;
|
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;
|
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
|
// 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
|
// 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
|
// 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("start: %d, end: %d \n", patternPos, pos);
|
||||||
|
//printf("patternPos: %d, pos: %d \n", patternPos, pos);
|
||||||
for (int j = 0; j < (pos-patternPos); j++) {
|
for (int j = 0; j < (pos-patternPos); j++) {
|
||||||
list_delete(evalList, patternPos);
|
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);
|
list_set(evalList, patternPos, resType, &resVal);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +287,7 @@ Arguments:
|
||||||
- Input String: char pointer (the source of the evaluation)
|
- Input String: char pointer (the source of the evaluation)
|
||||||
- Result: int pointer (where the result of the evaluation will be written)
|
- 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 i = 0;
|
||||||
int _len = strlen(inputStr);
|
int _len = strlen(inputStr);
|
||||||
// we want first to parse the expression and create a stack
|
// 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;
|
struct List evalList;
|
||||||
|
// NOTICE: for some reason the struct don't reset after a usage
|
||||||
|
list_reset(&evalList);
|
||||||
printf("\n - constructing list \n");
|
printf("\n - constructing list \n");
|
||||||
// initializing the evaluation list
|
// initializing the evaluation list
|
||||||
for (int j = 0; j < partitionPtr; j++) {
|
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];
|
char buff[_len+1];
|
||||||
|
buff[0] = 0;
|
||||||
|
|
||||||
// fill the buffer with the component string
|
// fill the buffer with the component string
|
||||||
for (int z = 0; z < len; z++) {
|
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)"
|
// TODO: SPLIT INTO A FUNCTION "identify_token(char* str)"
|
||||||
buff[len] = 0;
|
|
||||||
|
printf("buff: '%s' \n", buff);
|
||||||
|
|
||||||
char dumbValue = (char) 0;
|
char dumbValue = (char) 0;
|
||||||
|
|
||||||
|
if (buff[0] == '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (len == 1 && buff[0] == '(') {
|
if (len == 1 && buff[0] == '(') {
|
||||||
list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue);
|
list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue);
|
||||||
continue;
|
continue;
|
||||||
|
@ -341,11 +438,12 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (len == 1 && is_operator(buff[0])) {
|
if (len == 1 && is_operator(buff[0])) {
|
||||||
|
printf("found op\n");
|
||||||
char opValue = buff[0];
|
char opValue = buff[0];
|
||||||
list_set(&evalList, evalList.num_elements, TYPE_OPERATOR, &opValue);
|
list_set(&evalList, evalList.num_elements, TYPE_OPERATOR, &opValue);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int st = parse_int(buff, &res);
|
int st = parse_int(buff, &res);
|
||||||
if (st == 0) {
|
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);
|
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("end of l\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the content of this thing
|
// check the content of this thing
|
||||||
|
@ -383,10 +482,10 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) {
|
||||||
while (evalList.num_elements > 1) {
|
while (evalList.num_elements > 1) {
|
||||||
list_print(&evalList);
|
list_print(&evalList);
|
||||||
|
|
||||||
// we are going to look for pattern
|
// we are going to look for pattern to reduce
|
||||||
// - 0. OPENP NUM CLOSEP
|
// the order is really important here
|
||||||
// - 1. NUM OP NUM
|
|
||||||
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList);
|
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList);
|
||||||
|
int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList);
|
||||||
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
|
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
|
||||||
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
|
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
|
||||||
|
|
||||||
|
@ -401,7 +500,12 @@ int evaluate(char* inputStr, int* resultPtr, int* typePtr) {
|
||||||
return reduceOperatorOpStat;
|
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
|
// 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
|
// 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");
|
printf("ERR Evaluator: could not reduce more, dumping evalList: \n");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef EVALUATOR_H_
|
#ifndef EVALUATOR_H_
|
||||||
#define EVALUATOR_H_
|
#define EVALUATOR_H_
|
||||||
|
|
||||||
int evaluate(char* inputStr, int* resultPtr, int* typePtr);
|
int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
23
src/funcs.c
23
src/funcs.c
|
@ -2,16 +2,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "./types.h"
|
#include "./types.h"
|
||||||
#include "./repr_utils.h"
|
#include "./utils.h"
|
||||||
|
|
||||||
int abs_implementation(int* res, unsigned char* resType, unsigned char* types, int* args)
|
int abs_implementation(int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||||
{
|
{
|
||||||
if (types[0] == TYPE_INT) {
|
if (types[0] == TYPE_INT) {
|
||||||
|
*res = args[0];
|
||||||
if (args[0] < 0) {
|
if (args[0] < 0) {
|
||||||
*res = -args[0];
|
*res = -args[0];
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
*res = args[0];
|
|
||||||
*resType = TYPE_INT;
|
*resType = TYPE_INT;
|
||||||
return 0;
|
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)
|
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);
|
*res = *(int *)(&val);
|
||||||
*resType = TYPE_FLOAT;
|
*resType = TYPE_FLOAT;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -88,10 +87,10 @@ struct FuncIntro {
|
||||||
// void* are actually long!
|
// void* are actually long!
|
||||||
|
|
||||||
struct FuncIntro intros[] = {
|
struct FuncIntro intros[] = {
|
||||||
{"ABS", &abs_implementation, 1},
|
{"abs", &abs_implementation, 1},
|
||||||
{"SQRT", &sqrt_implementation, 1},
|
{"sqrt", &sqrt_implementation, 1},
|
||||||
{"MAX", &max_implementation, 2},
|
{"max", &max_implementation, 2},
|
||||||
{"GET_PI", &get_pi_implementation, 0},
|
{"get_pi", &get_pi_implementation, 0},
|
||||||
{"", 0, 0}
|
{"", 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,7 +134,13 @@ int execute_func(short funcID, short argsLen, unsigned char* argsTypes, int* arg
|
||||||
// call the function implementation
|
// call the function implementation
|
||||||
// first cast the function ptr
|
// first cast the function ptr
|
||||||
impl(resPtr, resTypePtr, argsTypes, argsValues);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,15 @@ int list_delete(struct List* list, int index)
|
||||||
return 0;
|
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)
|
int list_append_int(struct List* list, int value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,4 +68,6 @@ int list_delete(struct List* list, int index);
|
||||||
|
|
||||||
void list_print(struct List*);
|
void list_print(struct List*);
|
||||||
|
|
||||||
|
void list_reset(struct List* list);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "./list.h"
|
#include "./list.h"
|
||||||
#include "./number_parsing.h"
|
#include "./number_parsing.h"
|
||||||
#include "./evaluator.h"
|
#include "./evaluator.h"
|
||||||
#include "./repr_utils.h"
|
#include "./utils.h"
|
||||||
#include "./types.h"
|
#include "./types.h"
|
||||||
//int create_stack(int a, int b)
|
//int create_stack(int a, int b)
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "./number_parsing.h"
|
#include "./number_parsing.h"
|
||||||
|
#include "./utils.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_clean_positive_integer(int inputStrLen, char* inputStr, int* result) {
|
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;
|
cleanStrIntPart[cleanStrIntPartLen] = 0;
|
||||||
cleanStrFloatPart[cleanStrFloatPartLen] = 0;
|
cleanStrFloatPart[cleanStrFloatPartLen] = 0;
|
||||||
printf("clean str int part: /%s/ \n", cleanStrIntPart);
|
// printf("clean str int part: /%s/ \n", cleanStrIntPart);
|
||||||
printf("clean str float part: /%s/ \n", cleanStrFloatPart);
|
// printf("clean str float part: /%s/ \n", cleanStrFloatPart);
|
||||||
|
|
||||||
int intPart = 0;
|
int intPart = 0;
|
||||||
parse_clean_positive_integer(cleanStrIntPartLen, cleanStrIntPart, &intPart);
|
parse_clean_positive_integer(cleanStrIntPartLen, cleanStrIntPart, &intPart);
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
#include "./operate.h"
|
|
||||||
#include "./types.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "./operate.h"
|
||||||
|
#include "./types.h"
|
||||||
|
#include "./utils.h"
|
||||||
|
|
||||||
int is_operator(char candidate) {
|
int is_operator(char candidate) {
|
||||||
return (
|
return (
|
||||||
candidate == '*' ||
|
candidate == '*' ||
|
||||||
candidate == '/' ||
|
candidate == '/' ||
|
||||||
candidate == '+' ||
|
candidate == '+' ||
|
||||||
candidate == '-'
|
candidate == '-' ||
|
||||||
|
candidate == '^'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +51,8 @@ int operate(
|
||||||
res = a*b;
|
res = a*b;
|
||||||
} else if (operator == '/') {
|
} else if (operator == '/') {
|
||||||
res = a/b;
|
res = a/b;
|
||||||
|
} else if (operator == '^') {
|
||||||
|
res = 0;
|
||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +71,8 @@ int operate(
|
||||||
res = aRepr-bRepr;
|
res = aRepr-bRepr;
|
||||||
} else if (operator == '*') {
|
} else if (operator == '*') {
|
||||||
res = aRepr*bRepr;
|
res = aRepr*bRepr;
|
||||||
|
} else if (operator == '^') {
|
||||||
|
res = integer_pow(aRepr, bRepr);
|
||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
255
src/utils.c
Normal file
255
src/utils.c
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
38
src/utils.h
Normal file
38
src/utils.h
Normal file
|
@ -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
|
29
test.c
29
test.c
|
@ -3,7 +3,7 @@
|
||||||
#include "./src/list.h"
|
#include "./src/list.h"
|
||||||
#include "./src/number_parsing.h"
|
#include "./src/number_parsing.h"
|
||||||
#include "./src/funcs.h"
|
#include "./src/funcs.h"
|
||||||
#include "./src/repr_utils.h"
|
#include "./src/utils.h"
|
||||||
|
|
||||||
int some_computation(int a, int b, int* resPtr)
|
int some_computation(int a, int b, int* resPtr)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,16 @@ int some_computation(int a, int b, int* resPtr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float test_func(float x)
|
||||||
|
{
|
||||||
|
return m_float_pow(x,2)-2;
|
||||||
|
}
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
|
// test of euler
|
||||||
|
printf("lel : %f \n", m_sqrt(64));
|
||||||
|
|
||||||
|
|
||||||
// struct List l1;
|
// struct List l1;
|
||||||
|
|
||||||
// list_append_int(&l1, 4);
|
// list_append_int(&l1, 4);
|
||||||
|
@ -33,16 +42,16 @@ int main () {
|
||||||
// void* ptr = &res;
|
// void* ptr = &res;
|
||||||
|
|
||||||
// printf("%d\n", sizeof(ptr));
|
// printf("%d\n", sizeof(ptr));
|
||||||
int found = identify_func_name("ABS");
|
// int found = identify_func_name("ABS");
|
||||||
printf("found: %d \n", found);
|
// printf("found: %d \n", found);
|
||||||
|
|
||||||
unsigned char argsType[1] = { TYPE_FLOAT };
|
// unsigned char argsType[1] = { TYPE_FLOAT };
|
||||||
int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
// int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
||||||
int resVal = 0;
|
// int resVal = 0;
|
||||||
unsigned char resType = 0;
|
// unsigned char resType = 0;
|
||||||
execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
// execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
||||||
printf("func res type: %d \n", resType);
|
// printf("func res type: %d \n", resType);
|
||||||
printf("func res: %f \n", get_float_from_int_rep(resVal));
|
// printf("func res: %f \n", get_float_from_int_rep(resVal));
|
||||||
|
|
||||||
// int stat = parse_float("1052.254", &res);
|
// int stat = parse_float("1052.254", &res);
|
||||||
// printf("float parsing stat: %d \n", stat);
|
// printf("float parsing stat: %d \n", stat);
|
||||||
|
|
10
tests/test.c
Normal file
10
tests/test.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "./test_utils.h"
|
||||||
|
#include "./test_evaluation.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("== UNIT TESTS == \n");
|
||||||
|
test_utils();
|
||||||
|
test_evaluation();
|
||||||
|
}
|
60
tests/test_evaluation.c
Normal file
60
tests/test_evaluation.c
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
1
tests/test_evaluation.h
Normal file
1
tests/test_evaluation.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
void test_evaluation();
|
65
tests/test_utils.c
Normal file
65
tests/test_utils.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
1
tests/test_utils.h
Normal file
1
tests/test_utils.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
void test_utils();
|
Loading…
Reference in a new issue