diff --git a/README.md b/README.md index c999707..dc01e59 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,10 @@ I didn't really study how others languages works beforehand, I'm just guessing h ToDo List: -- [ ] pow operator +- [X] pow operator - [ ] binary operators -- [ ] implement basic math functions -- [ ] implement random_int(min, max) +- [X] implement basic math functions +- [X] implement random_int(min, max) - [ ] implement print_number(message) - [ ] implement input_number() - [ ] base of the CLI diff --git a/src/funcs.c b/src/funcs.c index 52144d9..c26bd30 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -1,10 +1,11 @@ #include #include -#include +#include +#include #include "./types.h" #include "./utils.h" -int abs_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) +int abs_impl(int* res, unsigned char* resType, unsigned char* types, int* args) { if (types[0] == TYPE_INT) { *res = args[0]; @@ -26,23 +27,83 @@ int abs_implementation(int* res, unsigned char* resType, unsigned char* types, i return 1; } -int sqrt_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) +int simple_float_func(float (*func)(float), int* res, unsigned char* resType, unsigned char* types, int* args) { float x = 0; if (types[0] == TYPE_INT) { - // convert to float x = (float) args[0]; } if (types[0] == TYPE_FLOAT) { x = get_float_from_int_rep(args[0]); } - *res = get_int_rep_from_float(sqrt(x)); + *res = get_int_rep_from_float(func(x)); *resType = TYPE_FLOAT; return 0; } -int max_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) +// #define SIMPLE_FUNC_BINDING(name) ({\ +// int #name_impl(int* res, unsigned char* resType, unsigned char* types, int* args)\ +// {\ +// return simple_float_func(&m_#name, res, resType, types, args);\ +// }\ +// }) +// +// +// SIMPLE_FUNC_BINDING(sqrt) +// +// SIMPLE_FUNC_BINDING(exp) +// SIMPLE_FUNC_BINDING(ln) +// SIMPLE_FUNC_BINDING(cos) +// SIMPLE_FUNC_BINDING(sin) +// SIMPLE_FUNC_BINDING(tan) + +int sqrt_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_sqrt, res, resType, types, args); +} + +int exp_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_exp, res, resType, types, args); +} + +int cos_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_cos, res, resType, types, args); +} + +int sin_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_sin, res, resType, types, args); +} + +int tan_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_tan, res, resType, types, args); +} + +int ln_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + return simple_float_func(&m_ln, res, resType, types, args); +} + +int log_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + float x = 0; + if (types[0] == TYPE_INT) { + x = (float) args[0]; + } + if (types[0] == TYPE_FLOAT) { + x = get_float_from_int_rep(args[0]); + } + *res = get_int_rep_from_float(m_log(10, x)); + *resType = TYPE_FLOAT; + + return 0; +} + +int max_impl(int* res, unsigned char* resType, unsigned char* types, int* args) { short maxIndex = 0; @@ -70,7 +131,7 @@ int max_implementation(int* res, unsigned char* resType, unsigned char* types, i return 0; } -int get_pi_implementation(int* res, unsigned char* resType, unsigned char* types, int* args) +int get_pi_impl(int* res, unsigned char* resType, unsigned char* types, int* args) { float val = CST_PI; *res = *(int *)(&val); @@ -78,6 +139,39 @@ int get_pi_implementation(int* res, unsigned char* resType, unsigned char* types return 0; } +/** +random_int(a, b) +Return a random int between a and b (a and b included) +*/ +int random_int_impl(int* res, unsigned char* resType, unsigned char* types, int* args) +{ + srand(time(NULL)); + + int lower = 1; + int upper = 10; + if (types[0] == TYPE_FLOAT) { + lower = (int) get_float_from_int_rep(args[0]); + } + if (types[1] == TYPE_FLOAT) { + upper = (int) get_float_from_int_rep(args[1]); + } + if (types[0] == TYPE_INT) { + lower = args[0]; + } + if (types[1] == TYPE_INT) { + upper = args[1]; + } + + int i; + + // rand returns a value between 0 and RAND_MAX (which is close to infinite) + int num = (rand() % (upper - lower + 1)) + lower; + *resType = TYPE_INT; + *res = num; + + return 0; +} + struct FuncIntro { char name[20]; int (*implementation)(int*, unsigned char*, unsigned char*, int*); @@ -87,10 +181,21 @@ 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_impl, 1}, + + {"sqrt", &sqrt_impl, 1}, + {"exp", &exp_impl, 1}, + + {"sin", &sin_impl, 1}, + {"cos", &cos_impl, 1}, + {"tan", &tan_impl, 1}, + {"ln", &ln_impl, 1}, + {"log", &log_impl, 1}, + + {"random_int", &random_int_impl, 2}, + + {"max", &max_impl, 2}, + {"get_pi", &get_pi_impl, 0}, {"", 0, 0} }; diff --git a/src/operate.c b/src/operate.c index 5dc34f0..e223067 100644 --- a/src/operate.c +++ b/src/operate.c @@ -52,7 +52,7 @@ int operate( } else if (operator == '/') { res = a/b; } else if (operator == '^') { - res = 0; + res = m_float_pow(a, b); } else { return 2; } diff --git a/src/utils.c b/src/utils.c index 76f4a90..c0dece5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -97,7 +97,8 @@ int m_factorial(int x) float m_exp(float x) { - const int n = 10; + // TODO: reduce the x to be more accurate in the exp computation + const int n = 13; float out = 0; for (int i = 0; i < n; i++) { out += m_float_pow(x, i)/m_factorial(i); @@ -163,7 +164,7 @@ float m_sin(float originalX) float m_cos(float x) { - return m_sin(x+2*CST_PI); + return m_sin(x+CST_PI/2); } float m_tan(float x) @@ -236,6 +237,19 @@ float m_ln(float x) return res; } +float m_log(float base, float x) +{ + // b^x = y + // log_b(b^x) = log_b(y) + // x = log_b(y) + + // exp(x ln(b)) = y + // x ln(b) = ln(y) + // x = ln(y)/ln(b) + + return m_ln(x)/m_ln(base); +} + int is_full_of_space(char* str) { int i = 0; diff --git a/tests/test_evaluation.c b/tests/test_evaluation.c index ca07a90..6e78861 100644 --- a/tests/test_evaluation.c +++ b/tests/test_evaluation.c @@ -57,4 +57,16 @@ void test_evaluation() evaluate("(abs((0-1)*2)) + abs(2)", &resVal, &resType); assert(resType == TYPE_INT); assert(4 == resVal); -} \ No newline at end of file + + evaluate("exp(2)-1", &resVal, &resType); + assert(resType == TYPE_FLOAT); + assert(float_almost_equal(6.389, get_float_from_int_rep(resVal))); + + evaluate("(cos(2)^2)+(sin(2)^2)", &resVal, &resType); + assert(resType == TYPE_FLOAT); + assert(float_almost_equal(1, get_float_from_int_rep(resVal))); + + evaluate("random_int(1, 100)", &resVal, &resType); + assert(resType == TYPE_INT); + printf(" - random int: %d \n", resVal); +}