From 04f0c9294a8da8c37ef3466fbcddf2a23b649608 Mon Sep 17 00:00:00 2001 From: Teddy Date: Sun, 11 Aug 2013 14:42:49 +0800 Subject: ... --- types.cpp | 906 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 906 insertions(+) create mode 100644 types.cpp (limited to 'types.cpp') diff --git a/types.cpp b/types.cpp new file mode 100644 index 0000000..c2e3bea --- /dev/null +++ b/types.cpp @@ -0,0 +1,906 @@ +#include "types.h" +#include "model.h" +#include "exc.h" +#include "consts.h" + +#include +#include +#include +#include + +const double EPS = 1e-16; +const int PREC = 16; + +EmptyList *empty_list = new EmptyList(); + +Pair::Pair(EvalObj *_car, EvalObj *_cdr) : + EvalObj(CLS_PAIR_OBJ), car(_car), cdr(_cdr), + next(NULL) {} + + ReprCons *Pair::get_repr_cons() { + return new PairReprCons(this, this); + } + +RetAddr::RetAddr(Pair *_addr) : FrameObj(CLS_RET_ADDR), addr(_addr) {} + +ParseBracket::ParseBracket(unsigned char _btype) : + FrameObj(CLS_SIM_OBJ | CLS_PAR_BRA), btype(_btype) {} + + UnspecObj::UnspecObj() : EvalObj(CLS_SIM_OBJ) {} + + ReprCons *UnspecObj::get_repr_cons() { + return new ReprStr("#"); + } + +SymObj::SymObj(const string &str) : + EvalObj(CLS_SIM_OBJ | CLS_SYM_OBJ), val(str) {} + + ReprCons *SymObj::get_repr_cons() { + return new ReprStr(val); + } + +OptObj::OptObj() : EvalObj(CLS_SIM_OBJ | CLS_OPT_OBJ) {} + +ProcObj::ProcObj(Pair *_body, + Environment *_envt, + EvalObj *_params) : + OptObj(), body(_body), params(_params), envt(_envt) {} + + Pair *ProcObj::call(Pair *args, Environment * &genvt, + Continuation * &cont, FrameObj ** &top_ptr) { + // Create a new continuation + // static_cast see `call` invocation in eval.cpp + Pair *ret_addr = static_cast(*top_ptr)->addr; + Continuation *_cont = new Continuation(genvt, ret_addr, cont, body); + // Create local env and recall the closure + Environment *_envt = new Environment(envt); + // static_cast because the params is already checked + EvalObj *ppar, *nptr; + for (ppar = params; + ppar->is_pair_obj(); + ppar = TO_PAIR(ppar)->cdr) + { + if ((nptr = args->cdr) != empty_list) + args = TO_PAIR(nptr); + else break; + _envt->add_binding(static_cast(TO_PAIR(ppar)->car), args->car); + } + + if (ppar->is_sym_obj()) + _envt->add_binding(static_cast(ppar), args->cdr); // (... . var_n) + else if (args->cdr != empty_list || ppar != empty_list) + throw TokenError("", RUN_ERR_WRONG_NUM_OF_ARGS); + + genvt = _envt; + cont = _cont; + *top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont + return body; // Move pc to the proc entry point + } + +ReprCons *ProcObj::get_repr_cons() { + return new ReprStr("#"); +} + +SpecialOptObj::SpecialOptObj(string _name) : OptObj(), name(_name) {} + +BoolObj::BoolObj(bool _val) : EvalObj(CLS_SIM_OBJ | CLS_BOOL_OBJ), val(_val) {} + +bool BoolObj::is_true() { return val; } + +ReprCons *BoolObj::get_repr_cons() { + return new ReprStr(val ? "#t" : "#f"); +} + +BoolObj *BoolObj::from_string(string repr) { + if (repr.length() != 2 || repr[0] != '#') + return NULL; + if (repr[1] == 't') + return new BoolObj(true); + else if (repr[1] == 'f') + return new BoolObj(false); + return NULL; +} + +NumObj::NumObj(NumLvl _level, bool _exactness) : + EvalObj(CLS_SIM_OBJ | CLS_NUM_OBJ), exactness(_exactness), level(_level) {} + + bool NumObj::is_exact() { return exactness; } + + StrObj::StrObj(string _str) : EvalObj(CLS_SIM_OBJ | CLS_STR_OBJ), str(_str) {} + + ReprCons *StrObj::get_repr_cons() { + return new ReprStr(str); + } + +CharObj::CharObj(char _ch) : EvalObj(CLS_SIM_OBJ | CLS_CHAR_OBJ), ch(_ch) {} + +CharObj *CharObj::from_string(string repr) { + size_t len = repr.length(); + if (len < 2) return NULL; + if (repr[0] != '#' || repr[1] != '\\') return NULL; + if (len == 3) return new CharObj(repr[2]); + string char_name = repr.substr(2, len - 2); + if (char_name == "newline") return new CharObj('\n'); + if (char_name == "space") return new CharObj(' '); + throw TokenError(char_name, RUN_ERR_UNKNOWN_CHAR_NAME); +} + +ReprCons *CharObj::get_repr_cons() { + string val = ""; + if (ch == ' ') val = "space"; + else if (ch == '\n') val = "newline"; + else val += ch; + return new ReprStr("#\\" + val); +} + +VecObj::VecObj() : EvalObj(CLS_SIM_OBJ | CLS_VECT_OBJ) {} + +EvalObj *VecObj::get_obj(int idx) { + return vec[idx]; +} + +size_t VecObj::get_size() { + return vec.end() - vec.begin(); +} + +void VecObj::resize(int new_size) { + vec.resize(new_size); +} + +void VecObj::push_back(EvalObj *new_elem) { + vec.push_back(new_elem); +} + +ReprCons *VecObj::get_repr_cons() { + return new VectReprCons(this, this); +} + +StrObj *StrObj::from_string(string repr) { + size_t len = repr.length(); + if (repr[0] == '\"' && repr[len - 1] == '\"') + return new StrObj(repr.substr(1, len - 2)); + return NULL; +} + +bool StrObj::lt(StrObj *r) { + return str < r->str; +} + +bool StrObj::gt(StrObj *r) { + return str > r->str; +} + +bool StrObj::le(StrObj *r) { + return str <= r->str; +} + +bool StrObj::ge(StrObj *r) { + return str >= r->str; +} + +bool StrObj::eq(StrObj *r) { + return str == r->str; +} + +BuiltinProcObj::BuiltinProcObj(BuiltinProc f, string _name) : + OptObj(), handler(f), name(_name) {} + + Pair *BuiltinProcObj::call(Pair *args, Environment * &envt, + Continuation * &cont, FrameObj ** &top_ptr) { + + Pair *ret_addr = static_cast(*top_ptr)->addr; + *top_ptr++ = handler(TO_PAIR(args->cdr), name); + return ret_addr->next; // Move to the next instruction + } + +ReprCons *BuiltinProcObj::get_repr_cons() { + return new ReprStr("#"); +} + +Environment::Environment(Environment *_prev_envt) : prev_envt(_prev_envt) {} + +bool Environment::add_binding(SymObj *sym_obj, EvalObj *eval_obj, bool def) { + bool has_key = binding.count(sym_obj->val); + if (!def && !has_key) return false; + binding[sym_obj->val] = eval_obj; + return true; +} + +EvalObj *Environment::get_obj(EvalObj *obj) { + if (!obj->is_sym_obj()) return obj; + SymObj *sym_obj = static_cast(obj); + + string name(sym_obj->val); + for (Environment *ptr = this; ptr; ptr = ptr->prev_envt) + { + bool has_key = ptr->binding.count(name); + if (has_key) return ptr->binding[name]; + } + // Object not found + throw TokenError(name, RUN_ERR_UNBOUND_VAR); +} + +Continuation::Continuation(Environment *_envt, Pair *_pc, + Continuation *_prev_cont, + Pair *_proc_body) : + prev_cont(_prev_cont), envt(_envt), pc(_pc), + proc_body(_proc_body) {} + + ReprCons::ReprCons(bool _done, EvalObj *_ori) : ori(_ori), done(_done) {} + ReprStr::ReprStr(string _repr) : ReprCons(true) { repr = _repr; } + EvalObj *ReprStr::next(const string &prev) { + throw NormalError(INT_ERR); + } + +PairReprCons::PairReprCons(Pair *_ptr, EvalObj *_ori) : + ReprCons(false, _ori), state(0), ptr(_ptr) {} + + EvalObj *PairReprCons::next(const string &prev) { + repr += prev; + EvalObj *res; + if (state == 0) + { + state = 1; + res = TO_PAIR(ptr)->car; + if (res->is_pair_obj()) + repr += "("; + return res; + } + else if (state == 1) + { + state = 2; + if (TO_PAIR(ptr)->car->is_pair_obj()) + repr += ")"; + ptr = TO_PAIR(ptr)->cdr; + if (ptr == empty_list) + return NULL; + repr += " "; + if (ptr->is_simple_obj()) + repr += ". "; + return ptr; + } + else + { + return NULL; + } + } + +VectReprCons::VectReprCons(VecObj *_ptr, EvalObj *_ori) : + ReprCons(false, _ori), ptr(_ptr), idx(0) { repr = "#("; } + + EvalObj *VectReprCons::next(const string &prev) { + repr += prev; + + if (idx && ptr->get_obj(idx - 1)->is_pair_obj()) + repr += ")"; + + if (idx == ptr->get_size()) + { + repr += ")"; + return NULL; + } + else + { + if (idx) repr += " "; + EvalObj *res = ptr->get_obj(idx++); + if (res->is_pair_obj()) + repr += "("; + return res; + } + } + +PromObj::PromObj(EvalObj *exp) : + EvalObj(CLS_SIM_OBJ | CLS_PROM_OBJ), entry(new Pair(exp, empty_list)), mem(NULL) {} + +Pair *PromObj::get_entry() { return entry; } + +ReprCons *PromObj::get_repr_cons() { return new ReprStr("#"); } + +EvalObj *PromObj::get_mem() { return mem; } + +void PromObj::feed_mem(EvalObj *res) { mem = res; } + + +string double_to_str(double val, bool force_sign = false) { + std::stringstream ss; + if (force_sign) ss << std::showpos; + ss << std::setprecision(PREC); + ss << val; + return ss.str(); +} + +string int_to_str(int val) { + std::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); +} + +bool is_zero(double x) { + return -EPS < x && x < EPS; +} + +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 + long long 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))) +#ifndef GMP_SUPPORT + real = int_ptr->val; +#else + real = int_ptr->val.get_d(); +#endif + else if ((rat_ptr = RatNumObj::from_string(real_str))) +#ifndef GMP_SUPPORT + real = rat_ptr->a / double(rat_ptr->b); +#else + real = rat_ptr->val.get_d(); +#endif + 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))) +#ifndef GMP_SUPPORT + imag = int_ptr->val; +#else + imag = int_ptr->val.get_d(); +#endif + else if ((rat_ptr = RatNumObj::from_string(imag_str))) +#ifndef GMP_SUPPORT + imag = rat_ptr->a / double(rat_ptr->b); +#else + imag = rat_ptr->val.get_d(); +#endif + 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(obj); break; + case NUM_LVL_REAL : + return new CompNumObj(static_cast(obj)->real, 0); + break; + case NUM_LVL_RAT : + { + RatNumObj *rat = static_cast(obj); +#ifndef GMP_SUPPORT + return new CompNumObj(rat->a / double(rat->b), 0); +#else + return new CompNumObj(rat->val.get_d(), 0); +#endif + break; + } + case NUM_LVL_INT : +#ifndef GMP_SUPPORT + return new CompNumObj(static_cast(obj)->val, 0); +#else + return new CompNumObj(static_cast(obj)->val.get_d(), 0); +#endif + } + throw NormalError(INT_ERR); +} + +#define A (real) +#define B (imag) +#define C (r->real) +#define D (r->imag) + +NumObj *CompNumObj::add(NumObj *_r) { + CompNumObj *r = static_cast(_r); + return new CompNumObj(A + C, B + D); +} + +NumObj *CompNumObj::sub(NumObj *_r) { + CompNumObj *r = static_cast(_r); + return new CompNumObj(A - C, B - D); +} + +NumObj *CompNumObj::mul(NumObj *_r) { + CompNumObj *r = static_cast(_r); + return new CompNumObj(A * C - B * D, + B * C + A * D); +} + +NumObj *CompNumObj::div(NumObj *_r) { + CompNumObj *r = static_cast(_r); + double f = C * C + D * D; + if (f == 0) + throw NormalError(RUN_ERR_NUMERIC_OVERFLOW); + f = 1 / f; + return new CompNumObj((A * C + B * D) * f, + (B * C - A * D) * f); +} + +bool NumObj::lt(NumObj *_r) { + throw TokenError("a comparable number", RUN_ERR_WRONG_TYPE); +} + +bool NumObj::gt(NumObj *_r) { + throw TokenError("a comparable number", RUN_ERR_WRONG_TYPE); +} + +bool NumObj::le(NumObj *_r) { + throw TokenError("a comparable number", RUN_ERR_WRONG_TYPE); +} + +bool NumObj::ge(NumObj *_r) { + throw TokenError("a comparable number", RUN_ERR_WRONG_TYPE); +} + +NumObj *NumObj::abs() { + throw TokenError("a real number", RUN_ERR_WRONG_TYPE); +} + + +bool CompNumObj::eq(NumObj *_r) { + CompNumObj *r = static_cast(_r); + return A == C && B == D; // TODO: more proper judgement +} + + +ReprCons *CompNumObj::get_repr_cons() { + return new ReprStr(double_to_str(real) + double_to_str(imag, true) + "i"); +} + +#undef A +#undef B +#undef C +#undef D + +RealNumObj::RealNumObj(double _real) : InexactNumObj(NUM_LVL_REAL), real(_real) {} + +RealNumObj *RealNumObj::from_string(string repr) { + bool flag; + double real = str_to_double(repr, flag); + if (!flag) return NULL; + return new RealNumObj(real); +} + +RealNumObj *RealNumObj::convert(NumObj *obj) { + switch (obj->level) + { + case NUM_LVL_REAL: + return static_cast(obj); break; + case NUM_LVL_RAT: + { + RatNumObj *rat = static_cast(obj); +#ifndef GMP_SUPPORT + return new RealNumObj(rat->a / double(rat->b)); +#else + return new RealNumObj(rat->val.get_d()); +#endif + break; + } + case NUM_LVL_INT: +#ifndef GMP_SUPPORT + return new RealNumObj(static_cast(obj)->val); +#else + return new RealNumObj(static_cast(obj)->val.get_d()); +#endif + + } + throw NormalError(INT_ERR); +} + +NumObj *RealNumObj::add(NumObj *_r) { + return new RealNumObj(real + static_cast(_r)->real); +} + +NumObj *RealNumObj::sub(NumObj *_r) { + return new RealNumObj(real - static_cast(_r)->real); +} + +NumObj *RealNumObj::mul(NumObj *_r) { + return new RealNumObj(real * static_cast(_r)->real); +} + +NumObj *RealNumObj::div(NumObj *_r) { + return new RealNumObj(real / static_cast(_r)->real); +} + +NumObj *RealNumObj::abs() { + return new RealNumObj(fabs(real)); +} + +bool RealNumObj::eq(NumObj *_r) { + return real == static_cast(_r)->real; +} + +bool RealNumObj::lt(NumObj *_r) { + return real < static_cast(_r)->real; +} + +bool RealNumObj::gt(NumObj *_r) { + return real > static_cast(_r)->real; +} + +bool RealNumObj::le(NumObj *_r) { + return real <= static_cast(_r)->real; +} + +bool RealNumObj::ge(NumObj *_r) { + return real >= static_cast(_r)->real; +} + + +ReprCons *RealNumObj::get_repr_cons() { + return new ReprStr(double_to_str(real)); +} + +ExactNumObj::ExactNumObj(NumLvl level) : NumObj(level, true) {} + +#ifndef GMP_SUPPORT +RatNumObj::RatNumObj(int _a, int _b) : + ExactNumObj(NUM_LVL_RAT), a(_a), b(_b) { + if (b == 0) + throw NormalError(RUN_ERR_NUMERIC_OVERFLOW); + if (b < 0) a = -a, b = -b; + int g = gcd(a, b); + a /= g; + b /= g; + } + +RatNumObj *RatNumObj::from_string(string repr) { + int a, b; + size_t len = repr.length(); + int pos = -1; + for (size_t i = 0; i < len; i++) + if (repr[i] == '/') { pos = i; break; } + bool flag; + a = str_to_int(repr.substr(0, pos), flag); + if (!flag) return NULL; + b = str_to_int(repr.substr(pos + 1, len - pos - 1), flag); + if (!flag) return NULL; + + return new RatNumObj(a, b); +} +#else +RatNumObj::RatNumObj(mpq_class _val) : + ExactNumObj(NUM_LVL_RAT), val(_val) { + val.canonicalize(); +} + +RatNumObj *RatNumObj::from_string(string repr) { + try + { + mpq_class ret(repr, 10); + if (ret.get_den() == 0) + throw NormalError(RUN_ERR_NUMERIC_OVERFLOW); + ret.canonicalize(); + return new RatNumObj(ret); + } + catch (std::invalid_argument &e) + { + return NULL; + } +} +#endif + + +RatNumObj *RatNumObj::convert(NumObj *obj) { + switch (obj->level) + { + case NUM_LVL_RAT: + return static_cast(obj); break; + case NUM_LVL_INT: +#ifndef GMP_SUPPORT + return new RatNumObj(static_cast(obj)->val, 1); +#else + return new RatNumObj(mpq_class( + static_cast(obj)->val, + mpz_class(1))); +#endif + } + throw NormalError(INT_ERR); +} + +#define A (a) +#define B (b) +#define C (r->a) +#define D (r->b) + +NumObj *RatNumObj::add(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + int na = A * D + B * C, nb = B * D; + int g = gcd(na, nb); + na /= g; + nb /= g; + return new RatNumObj(na, nb); +#else + return new RatNumObj(val + r->val); +#endif +} + +NumObj *RatNumObj::sub(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + int na = A * D - B * C, nb = B * D; + int g = gcd(na, nb); + na /= g; + nb /= g; + return new RatNumObj(na, nb); +#else + return new RatNumObj(val - r->val); +#endif +} + +NumObj *RatNumObj::mul(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + int na = A * C, nb = B * D; + int g = gcd(na, nb); + na /= g; + nb /= g; + return new RatNumObj(na, nb); +#else + return new RatNumObj(val * r->val); +#endif +} + +NumObj *RatNumObj::div(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + int na = A * D, nb = B * C; + int g = gcd(na, nb); + na /= g; + nb /= g; + return new RatNumObj(na, nb); +#else + return new RatNumObj(val / r->val); +#endif +} + +bool RatNumObj::lt(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + return A * D < C * B; +#else + return val < r->val; +#endif +} + +bool RatNumObj::gt(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + return A * D > C * B; +#else + return val > r->val; +#endif +} + +bool RatNumObj::le(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + return A * D <= C * B; +#else + return val <= r->val; +#endif +} + +bool RatNumObj::ge(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + return A * D >= C * B; +#else + return val >= r->val; +#endif +} + + +bool RatNumObj::eq(NumObj *_r) { + RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT + return A * D == C * B; +#else + return val == r->val; +#endif +} + +NumObj *RatNumObj::abs() { +#ifndef GMP_SUPPORT + return new RatNumObj((a > 0 ? a : -a), b); +#else + return new RatNumObj(std::abs(val)); +#endif +} + +ReprCons *RatNumObj::get_repr_cons() { +#ifndef GMP_SUPPORT + return new ReprStr(int_to_str(A) + "/" + int_to_str(B)); +#else + return new ReprStr(val.get_str()); +#endif +} + + +#ifndef GMP_SUPPORT +IntNumObj::IntNumObj(int _val) : ExactNumObj(NUM_LVL_INT), val(_val) {} +IntNumObj *IntNumObj::from_string(string repr) { + int val = 0; + for (size_t i = 0; i < repr.length(); i++) + { + if (!('0' <= repr[i] && repr[i] <= '9')) + return NULL; + val = val * 10 + repr[i] - '0'; + } + return new IntNumObj(val); +} +int IntNumObj::get_i() { return val; } +#else +IntNumObj::IntNumObj(mpz_class _val) : ExactNumObj(NUM_LVL_INT), val(_val) {} +IntNumObj *IntNumObj::from_string(string repr) { + try + { + mpz_class ret(repr, 10); + return new IntNumObj(ret); + } + catch (std::invalid_argument &e) + { + return NULL; + } +} +int IntNumObj::get_i() { return val.get_si(); } +#endif + +IntNumObj *IntNumObj::convert(NumObj *obj) { + switch (obj->level) + { + case NUM_LVL_INT : + return static_cast(obj); + default: + throw NormalError(INT_ERR); + } +} + +NumObj *IntNumObj::add(NumObj *_r) { + return new IntNumObj(val + static_cast(_r)->val); +} + +NumObj *IntNumObj::sub(NumObj *_r) { + return new IntNumObj(val - static_cast(_r)->val); +} + +NumObj *IntNumObj::mul(NumObj *_r) { + return new IntNumObj(val * static_cast(_r)->val); +} + +NumObj *IntNumObj::div(NumObj *_r) { +#ifndef GMP_SUPPORT + return new RatNumObj(val, static_cast(_r)->val); +#else + mpz_class d(static_cast(_r)->val); + if (d == 0) throw NormalError(RUN_ERR_NUMERIC_OVERFLOW); + return new RatNumObj(mpq_class(val, d)); +#endif +} + +NumObj *IntNumObj::abs() { + return new IntNumObj(std::abs(val)); +} + +NumObj *IntNumObj::rem(NumObj *_r) { + return new IntNumObj(val % static_cast(_r)->val); +} + +NumObj *IntNumObj::mod(NumObj *_r) { + const mpz_class &rval = static_cast(_r)->val; + mpz_class ret = val % rval; + if (sgn(ret) != sgn(rval)) + ret = ret + rval; + return new IntNumObj(ret); +} + +NumObj *IntNumObj::quo(NumObj *_r) { + return new IntNumObj(val / static_cast(_r)->val); +} + +NumObj *IntNumObj::gcd(NumObj *_r) { + mpz_t g; + mpz_gcd(g, val.get_mpz_t(), static_cast(_r)->val.get_mpz_t()); + return new IntNumObj(mpz_class(g)); +} + +NumObj *IntNumObj::lcm(NumObj *_r) { + mpz_t l; + mpz_lcm(l, val.get_mpz_t(), static_cast(_r)->val.get_mpz_t()); + return new IntNumObj(mpz_class(l)); +} + +bool IntNumObj::lt(NumObj *_r) { + return val < static_cast(_r)->val; +} + +bool IntNumObj::gt(NumObj *_r) { + return val > static_cast(_r)->val; +} + +bool IntNumObj::le(NumObj *_r) { + return val <= static_cast(_r)->val; +} + +bool IntNumObj::ge(NumObj *_r) { + return val >= static_cast(_r)->val; +} + + +bool IntNumObj::eq(NumObj *_r) { + return val == static_cast(_r)->val; +} + +ReprCons *IntNumObj::get_repr_cons() { +#ifndef GMP_SUPPORT + return new ReprStr(int_to_str(val)); +#else + return new ReprStr(val.get_str()); +#endif +} -- cgit v1.2.3