2019-01-14 03:16:25 +01:00
|
|
|
|
#include <stdlib.h>
|
2019-01-21 18:44:56 +01:00
|
|
|
|
#include <limits.h>
|
2019-01-14 03:16:25 +01:00
|
|
|
|
#include <string.h>
|
2019-01-21 18:44:56 +01:00
|
|
|
|
#include <math.h>
|
2019-01-14 03:16:25 +01:00
|
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
|
|
2019-01-22 00:08:27 +01:00
|
|
|
|
#define SPECIALFORMSNUM 2
|
|
|
|
|
int isSpecialForm(char *symbol)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
|
char *specialForms[] =
|
|
|
|
|
{
|
|
|
|
|
"навод",
|
|
|
|
|
"дефиниши"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < SPECIALFORMSNUM; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp(symbol, specialForms[i]))
|
|
|
|
|
{
|
|
|
|
|
result = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-14 03:16:25 +01:00
|
|
|
|
int properList(object list)
|
|
|
|
|
{
|
|
|
|
|
object *current = &list;
|
|
|
|
|
while (TYPE(*current) == consObject)
|
|
|
|
|
{
|
|
|
|
|
current = &CDR(*current);
|
|
|
|
|
}
|
|
|
|
|
return TYPE(*current) == nilObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int listLength(object list)
|
|
|
|
|
{
|
|
|
|
|
object *current = &list;
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (TYPE(*current) != nilObject)
|
|
|
|
|
{
|
|
|
|
|
current = &CDR(*current);
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void deleteObject(object input)
|
|
|
|
|
{
|
|
|
|
|
if ((TYPE(input) == symbolObject) && SYM(input) != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(SYM(input));
|
|
|
|
|
SYM(input) = NULL;
|
|
|
|
|
}
|
|
|
|
|
else if (TYPE(input) == consObject)
|
|
|
|
|
{
|
|
|
|
|
deleteObject(CAR(input));
|
|
|
|
|
deleteObject(CDR(input));
|
|
|
|
|
free(CONS(input));
|
|
|
|
|
CONS(input) = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TYPE(input) = nilObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object copyObject(object input)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
TYPE(result) = TYPE(input);
|
|
|
|
|
if (TYPE(input) == errorObject)
|
|
|
|
|
{
|
2019-01-16 23:24:23 +01:00
|
|
|
|
ERR(result) = ERR(input);
|
2019-01-14 03:16:25 +01:00
|
|
|
|
}
|
|
|
|
|
else if (TYPE(input) == numberObject)
|
|
|
|
|
{
|
|
|
|
|
NUM(result) = NUM(input);
|
|
|
|
|
}
|
|
|
|
|
else if (TYPE(input) == symbolObject)
|
|
|
|
|
{
|
|
|
|
|
SYM(result) =
|
|
|
|
|
malloc(sizeof(char) * (strlen(SYM(input)) + 1));
|
|
|
|
|
strcpy(SYM(result), SYM(input));
|
|
|
|
|
}
|
|
|
|
|
else if (TYPE(input) == consObject)
|
|
|
|
|
{
|
|
|
|
|
CONS(result) = malloc(sizeof(cons));
|
|
|
|
|
CAR(result) = copyObject(CAR(input));
|
|
|
|
|
CDR(result) = copyObject(CDR(input));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-20 23:48:12 +01:00
|
|
|
|
|
|
|
|
|
object longlongToNumber(long long int input)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
NUM_TYPE(result) = fractionNum;
|
|
|
|
|
NUM_NUMER(result) = input;
|
|
|
|
|
NUM_DENOM(result) = 1LL;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object exactToInexactNum(object a)
|
|
|
|
|
{
|
|
|
|
|
object result = copyObject(a);
|
|
|
|
|
|
|
|
|
|
if (TYPE(result) == numberObject && NUM_TYPE(result) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_TYPE(result) = realNum;
|
|
|
|
|
NUM_REAL(result) = (long double) NUM_NUMER(result) /
|
|
|
|
|
(long double) NUM_DENOM(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 18:44:56 +01:00
|
|
|
|
object inexactToExactNum(object a)
|
|
|
|
|
{
|
|
|
|
|
object result = copyObject(a);
|
|
|
|
|
|
|
|
|
|
if (TYPE(result) == numberObject && NUM_TYPE(result) == realNum)
|
|
|
|
|
{
|
|
|
|
|
long long int divisor = 1;
|
|
|
|
|
while (NUM_REAL(result) != floorl(NUM_REAL(result)) &&
|
|
|
|
|
divisor <= INT_MAX)
|
|
|
|
|
{
|
|
|
|
|
NUM_REAL(result) *= 10.0L;
|
|
|
|
|
divisor *= 10LL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NUM_TYPE(result) = fractionNum;
|
|
|
|
|
NUM_NUMER(result) = (long long int) floorl(NUM_REAL(result));
|
|
|
|
|
NUM_DENOM(result) = divisor;
|
|
|
|
|
|
|
|
|
|
result = shortenFractionNum(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-20 23:48:12 +01:00
|
|
|
|
long long int gcd(long long int a, long long int b)
|
|
|
|
|
/* највећи заједнички делилац */
|
|
|
|
|
{
|
|
|
|
|
if (b == 0LL)
|
|
|
|
|
{
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return gcd(b, a - b * (a / b));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
long long int lcm(long long int a, long long int b)
|
|
|
|
|
/* најмањи заједнички садржалац */
|
|
|
|
|
{
|
|
|
|
|
if (a == 0LL && b == 0LL)
|
|
|
|
|
{
|
|
|
|
|
return 0L;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return llabs(a * b) / gcd(a, b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object shortenFractionNum(object a)
|
|
|
|
|
/* скраћује разломак, враћа грешку ако је неправилан разломак, уколико улаз
|
|
|
|
|
* заиста јесте дат као разломак */
|
|
|
|
|
{
|
|
|
|
|
object result = copyObject(a);
|
|
|
|
|
|
|
|
|
|
if (TYPE(result) == numberObject && NUM_TYPE(result) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
if (NUM_DENOM(result) == 0)
|
|
|
|
|
{
|
|
|
|
|
deleteObject(result);
|
|
|
|
|
TYPE(result) = errorObject;
|
|
|
|
|
ERR(result) = divisionByZeroError;
|
|
|
|
|
}
|
|
|
|
|
else if (NUM_NUMER(result) == 0)
|
|
|
|
|
{
|
|
|
|
|
NUM_DENOM(result) = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
long long int divisor =
|
|
|
|
|
gcd(NUM_NUMER(result), NUM_DENOM(result));
|
|
|
|
|
NUM_NUMER(result) /= divisor;
|
|
|
|
|
NUM_DENOM(result) /= divisor;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object plusNum(object a, object b)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
|
|
|
|
|
if (NUM_TYPE(a) == fractionNum && NUM_TYPE(b) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_TYPE(result) = fractionNum;
|
|
|
|
|
NUM_NUMER(result) = NUM_NUMER(a) * NUM_DENOM(b) + NUM_NUMER(b) * NUM_DENOM(a);
|
|
|
|
|
NUM_DENOM(result) = NUM_DENOM(a) * NUM_DENOM(b);
|
|
|
|
|
/*
|
|
|
|
|
* TODO: имплементирати оптималнији начин множења разломака
|
|
|
|
|
long long int denominator = lcm(NUM_DENOM(a), NUM_DENOM(b));
|
|
|
|
|
NUM_NUMER(result) =
|
|
|
|
|
NUM_NUMER(a) * (denominator / NUM_DENOM(a)) +
|
|
|
|
|
NUM_NUMER(b) * (denominator / NUM_DENOM(b));
|
|
|
|
|
*/
|
|
|
|
|
result = shortenFractionNum(result);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NUM_TYPE(result) = realNum;
|
|
|
|
|
NUM_REAL(result) = NUM_REAL(exactToInexactNum(a))
|
|
|
|
|
+ NUM_REAL(exactToInexactNum(b));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object minusNum(object a)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
result = copyObject(a);
|
|
|
|
|
|
|
|
|
|
if (NUM_TYPE(result) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_NUMER(result) = -NUM_NUMER(result);
|
|
|
|
|
}
|
|
|
|
|
else if (NUM_TYPE(result) == realNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_REAL(result) = -NUM_REAL(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object timesNum(object a, object b)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
TYPE(result) = numberObject;
|
|
|
|
|
|
|
|
|
|
if (NUM_TYPE(a) == fractionNum && NUM_TYPE(b) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_TYPE(result) = fractionNum;
|
|
|
|
|
NUM_NUMER(result) = NUM_NUMER(a) * NUM_NUMER(b);
|
|
|
|
|
NUM_DENOM(result) = NUM_DENOM(a) * NUM_DENOM(b);
|
|
|
|
|
result = shortenFractionNum(result);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NUM_TYPE(result) = realNum;
|
|
|
|
|
NUM_REAL(result) = NUM_REAL(exactToInexactNum(a)) *
|
|
|
|
|
NUM_REAL(exactToInexactNum(b));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object inverseNum(object a)
|
|
|
|
|
{
|
|
|
|
|
object result;
|
|
|
|
|
result = copyObject(a);
|
|
|
|
|
|
|
|
|
|
if (NUM_TYPE(result) == fractionNum)
|
|
|
|
|
{
|
|
|
|
|
if (NUM_NUMER(result) == 0)
|
|
|
|
|
{
|
|
|
|
|
deleteObject(result);
|
|
|
|
|
TYPE(result) = errorObject;
|
|
|
|
|
ERR(result) = divisionByZeroError;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NUM_NUMER(result) = NUM_DENOM(a);
|
|
|
|
|
NUM_DENOM(result) = NUM_NUMER(a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (NUM_TYPE(result) == realNum)
|
|
|
|
|
{
|
|
|
|
|
NUM_REAL(result) = 1.0L/NUM_REAL(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|