#include "exc.h"
#include "consts.h"
#include "builtin.h"
#include "model.h"
#include "exc.h"
#include <cstdio>
#include <sstream>
#include <cctype>
#include <cstdlib>
using std::stringstream;
extern EmptyList *empty_list;
static const int NUM_LVL_COMP = 0;
static const int NUM_LVL_REAL = 1;
static const int NUM_LVL_RAT = 2;
static const int NUM_LVL_INT = 3;
string double_to_str(double val, bool force_sign = false) {
stringstream ss;
if (force_sign) ss << std::showpos;
ss << val;
return ss.str();
}
string int_to_str(int val) {
stringstream ss;
ss << val;
return ss.str();
}
double str_to_double(string repr, bool &flag) {
const char *nptr = repr.c_str();
char *endptr;
double val = strtod(nptr, &endptr);
if (endptr == nptr || endptr != nptr + repr.length())
{
flag = false;
return 0;
}
flag = true;
return val;
}
int str_to_int(string repr, bool &flag) {
const char *nptr = repr.c_str();
char *endptr;
int val = strtol(nptr, &endptr, 10);
if (endptr == nptr || endptr != nptr + repr.length())
{
flag = false;
return 0;
}
flag = true;
return val;
}
int gcd(int a, int b) {
int t;
while (b) t = b, b = a % b, a = t;
return abs(a);
}
InexactNumObj::InexactNumObj(NumLvl level) : NumObj(level, false) {}
CompNumObj::CompNumObj(double _real, double _imag) :
InexactNumObj(NUM_LVL_COMP), real(_real), imag(_imag) {}
CompNumObj *CompNumObj::from_string(string repr) {
// spos: the position of the last sign
// ipos: the position of i
int spos = -1, ipos = -1;
size_t len = repr.length();
bool sign;
for (size_t i = 0; i < len; i++)
if (repr[i] == '+' || repr[i] == '-')
{
spos = i;
sign = repr[i] == '-';
}
else if (repr[i] == 'i' || repr[i] == 'I')
ipos = i;
if (spos == -1 || ipos == -1 || !(spos < ipos))
return NULL;
double real = 0, imag = 1;
IntNumObj *int_ptr;
RatNumObj *rat_ptr;
RealNumObj *real_ptr;
if (spos > 0)
{
string real_str = repr.substr(0, spos);
if (int_ptr = IntNumObj::from_string(real_str))
real = int_ptr->val;
else if ((rat_ptr = RatNumObj::from_string(real_str)))
real = rat_ptr->a / double(rat_ptr->b);
else if ((real_ptr = RealNumObj::from_string(real_str)))
real = real_ptr->real;
else return NULL;
}
if (ipos > spos + 1)
{
string imag_str = repr.substr(spos + 1, ipos - spos - 1);
if (int_ptr = IntNumObj::from_string(imag_str))
imag = int_ptr->val;
else if ((rat_ptr = RatNumObj::from_string(imag_str)))
imag = rat_ptr->a / double(rat_ptr->b);
else if ((real_ptr = RealNumObj::from_string(imag_str)))
imag = real_ptr->real;
else return NULL;
}
if (sign) imag = -imag;
return new CompNumObj(real, imag);
}
CompNumObj *CompNumObj::convert(NumObj *obj) {
switch (obj->level)
{
case NUM_LVL_COMP :
return static_cast<CompNumObj*>(obj); break;
case NUM_LVL_REAL :
return new CompNumObj(static_cast<RealNumObj*>(obj)->real, 0);
break;
case NUM_LVL_RAT :
{
RatNumObj *rat = static_cast<RatNumObj*>(obj);
return new CompNumObj(rat->a / double(rat->b), 0);
break;
}
case NUM_LVL_INT :
return new CompNumObj(static_cast<IntNumObj*>(obj)->val, 0);
}
throw NormalError(INT_ERR);
}
#define A (real)
#define B (imag)
#define C (r->real)
#define D (r->imag)
NumObj *CompNumObj::plus(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_r);
return new