feat: add basic math and random_int funcs

This commit is contained in:
Matthieu Bessat 2022-04-30 18:01:22 +02:00
parent a62dd411aa
commit cb2a1df61f
5 changed files with 149 additions and 18 deletions

View file

@ -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

View file

@ -1,10 +1,11 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#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}
};

View file

@ -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;
}

View file

@ -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;

View file

@ -57,4 +57,16 @@ void test_evaluation()
evaluate("(abs((0-1)*2)) + abs(2)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(4 == resVal);
}
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);
}