From e0c274fc6b7dc1c500ceb1375c2a8c4a09c1018c Mon Sep 17 00:00:00 2001 From: Teddy Date: Wed, 7 Aug 2013 15:43:54 +0800 Subject: added GMP support --- Makefile | 4 +- TODO.rst | 1 - builtin.cpp | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- builtin.h | 40 ++++++++++------ eval.cpp | 2 +- model.h | 6 +-- 6 files changed, 165 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 4c2071c..3a3f37a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ main: main.o parser.o builtin.o model.o eval.o exc.o consts.o - g++ -o main $^ -pg + g++ -o main $^ -pg -lgmp .cpp.o: - g++ $< -c -g -pg -DDEBUG + g++ $< -c -g -pg -DDEBUG -DGMP_SUPPORT clean: rm -f *.o diff --git a/TODO.rst b/TODO.rst index b90ca50..02693d7 100644 --- a/TODO.rst +++ b/TODO.rst @@ -1,2 +1 @@ -- GMP - Add macro support diff --git a/builtin.cpp b/builtin.cpp index 394f417..2c951b6 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -117,9 +117,17 @@ CompNumObj::CompNumObj(double _real, double _imag) : { 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; @@ -128,9 +136,17 @@ CompNumObj::CompNumObj(double _real, double _imag) : { 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; @@ -150,11 +166,19 @@ CompNumObj *CompNumObj::convert(NumObj *obj) { 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); } @@ -164,17 +188,17 @@ CompNumObj *CompNumObj::convert(NumObj *obj) { #define C (r->real) #define D (r->imag) -NumObj *CompNumObj::plus(NumObj *_r) { +NumObj *CompNumObj::add(NumObj *_r) { CompNumObj *r = static_cast(_r); return new CompNumObj(A + C, B + D); } -NumObj *CompNumObj::minus(NumObj *_r) { +NumObj *CompNumObj::sub(NumObj *_r) { CompNumObj *r = static_cast(_r); return new CompNumObj(A - C, B - D); } -NumObj *CompNumObj::multi(NumObj *_r) { +NumObj *CompNumObj::mul(NumObj *_r) { CompNumObj *r = static_cast(_r); return new CompNumObj(A * C - B * D, B * C + A * D); @@ -227,24 +251,33 @@ RealNumObj *RealNumObj::convert(NumObj *obj) { 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::plus(NumObj *_r) { +NumObj *RealNumObj::add(NumObj *_r) { return new RealNumObj(real + static_cast(_r)->real); } -NumObj *RealNumObj::minus(NumObj *_r) { +NumObj *RealNumObj::sub(NumObj *_r) { return new RealNumObj(real - static_cast(_r)->real); } -NumObj *RealNumObj::multi(NumObj *_r) { +NumObj *RealNumObj::mul(NumObj *_r) { return new RealNumObj(real * static_cast(_r)->real); } @@ -270,6 +303,7 @@ string RealNumObj::ext_repr() { ExactNumObj::ExactNumObj(NumLvl level) : NumObj(level, true) {} +#ifndef GMP_SUPPORT RatNumObj::RatNumObj(int _a, int _b) : ExactNumObj(NUM_LVL_RAT), a(_a), b(_b) { int g = gcd(a, b); @@ -291,6 +325,25 @@ RatNumObj *RatNumObj::from_string(string repr) { 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); + return new RatNumObj(ret); + } + catch (std::invalid_argument &e) + { + return NULL; + } +} +#endif + RatNumObj *RatNumObj::convert(NumObj *obj) { switch (obj->level) @@ -298,7 +351,13 @@ RatNumObj *RatNumObj::convert(NumObj *obj) { 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); } @@ -308,63 +367,96 @@ RatNumObj *RatNumObj::convert(NumObj *obj) { #define C (r->a) #define D (r->b) -NumObj *RatNumObj::plus(NumObj *_r) { +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::minus(NumObj *_r) { +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::multi(NumObj *_r) { +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::eq(NumObj *_r) { RatNumObj *r = static_cast(_r); +#ifndef GMP_SUPPORT return A * D == C * B; +#else + return val == r->val; +#endif } string RatNumObj::ext_repr() { +#ifndef GMP_SUPPORT return int_to_str(A) + "/" + int_to_str(B); +#else + return val.get_str(); +#endif } -IntNumObj::IntNumObj(int _val) : ExactNumObj(NUM_LVL_INT), val(_val) {} +#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++) @@ -375,6 +467,20 @@ IntNumObj *IntNumObj::from_string(string repr) { } return new IntNumObj(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; + } +} +#endif IntNumObj *IntNumObj::convert(NumObj *obj) { switch (obj->level) @@ -386,21 +492,25 @@ IntNumObj *IntNumObj::convert(NumObj *obj) { } } -NumObj *IntNumObj::plus(NumObj *_r) { - +NumObj *IntNumObj::add(NumObj *_r) { return new IntNumObj(val + static_cast(_r)->val); } -NumObj *IntNumObj::minus(NumObj *_r) { +NumObj *IntNumObj::sub(NumObj *_r) { return new IntNumObj(val - static_cast(_r)->val); } -NumObj *IntNumObj::multi(NumObj *_r) { +NumObj *IntNumObj::mul(NumObj *_r) { return new IntNumObj(val * static_cast(_r)->val); } NumObj *IntNumObj::div(NumObj *_r) { - return new IntNumObj(val / static_cast(_r)->val); +#ifndef GMP_SUPPORT + return new RatNumObj(val, static_cast(_r)->val); +#else + return new RatNumObj(mpq_class(val, + static_cast(_r)->val)); +#endif } bool IntNumObj::lt(NumObj *_r) { @@ -416,7 +526,11 @@ bool IntNumObj::eq(NumObj *_r) { } string IntNumObj::ext_repr() { +#ifndef GMP_SUPPORT return int_to_str(val); +#else + return val.get_str(); +#endif } SpecialOptIf::SpecialOptIf() : SpecialOptObj("if") {} @@ -741,7 +855,7 @@ BUILTIN_PROC_DEF(num_add) { opr = _res->convert(opr); else _res = opr->convert(_res); - res = _res->plus(opr); + res = _res->add(opr); if ((nptr = args->cdr)->is_cons_obj()) args = TO_CONS(nptr); @@ -774,14 +888,14 @@ BUILTIN_PROC_DEF(num_sub) { opr = _res->convert(opr); else _res = opr->convert(_res); - res = _res->minus(opr); + res = _res->sub(opr); } if (args->cdr != empty_list) throw TokenError(name, RUN_ERR_WRONG_NUM_OF_ARGS); return res; } -BUILTIN_PROC_DEF(num_multi) { +BUILTIN_PROC_DEF(num_mul) { ARGS_AT_LEAST_ONE; NumObj *res = new IntNumObj(1), *opr; // the most accurate type EvalObj *nptr; @@ -795,7 +909,7 @@ BUILTIN_PROC_DEF(num_multi) { opr = _res->convert(opr); else _res = opr->convert(_res); - res = _res->multi(opr); + res = _res->mul(opr); if ((nptr = args->cdr)->is_cons_obj()) args = TO_CONS(nptr); diff --git a/builtin.h b/builtin.h index a01c93e..b6585f3 100644 --- a/builtin.h +++ b/builtin.h @@ -3,6 +3,7 @@ #include "model.h" #include +#include using std::string; @@ -32,9 +33,9 @@ class CompNumObj: public InexactNumObj { /** Convert to a complex number from other numeric types */ CompNumObj *convert(NumObj* obj); - NumObj *plus(NumObj *r); - NumObj *minus(NumObj *r); - NumObj *multi(NumObj *r); + NumObj *add(NumObj *r); + NumObj *sub(NumObj *r); + NumObj *mul(NumObj *r); NumObj *div(NumObj *r); bool lt(NumObj *r); bool gt(NumObj *r); @@ -57,9 +58,9 @@ class RealNumObj: public InexactNumObj { /** Convert to a real number from other numeric types */ RealNumObj *convert(NumObj* obj); - NumObj *plus(NumObj *r); - NumObj *minus(NumObj *r); - NumObj *multi(NumObj *r); + NumObj *add(NumObj *r); + NumObj *sub(NumObj *r); + NumObj *mul(NumObj *r); NumObj *div(NumObj *r); bool lt(NumObj *r); bool gt(NumObj *r); @@ -82,9 +83,14 @@ class ExactNumObj: public NumObj { */ class RatNumObj: public ExactNumObj { public: +#ifndef GMP_SUPPORT int a, b; /** Construct a rational number */ RatNumObj(int _a, int _b); +#else + mpq_class val; + RatNumObj(mpq_class val); +#endif /** Try to construct an RatNumObj object * @return NULL if failed */ @@ -92,9 +98,9 @@ class RatNumObj: public ExactNumObj { /** Convert to a Rational number from other numeric types */ RatNumObj *convert(NumObj* obj); - NumObj *plus(NumObj *r); - NumObj *minus(NumObj *r); - NumObj *multi(NumObj *r); + NumObj *add(NumObj *r); + NumObj *sub(NumObj *r); + NumObj *mul(NumObj *r); NumObj *div(NumObj *r); bool lt(NumObj *r); bool gt(NumObj *r); @@ -107,9 +113,15 @@ class RatNumObj: public ExactNumObj { */ class IntNumObj: public ExactNumObj { public: +#ifndef GMP_SUPPORT int val; /** Construct a integer */ - IntNumObj(int _val); + IntNumObj(int val); +#else + mpz_class val; + /** Construct a integer */ + IntNumObj(mpz_class val); +#endif /** Try to construct an IntNumObj object * @return NULL if failed */ @@ -117,9 +129,9 @@ class IntNumObj: public ExactNumObj { /** Convert to a integer from other numeric types */ IntNumObj *convert(NumObj* obj); - NumObj *plus(NumObj *r); - NumObj *minus(NumObj *r); - NumObj *multi(NumObj *r); + NumObj *add(NumObj *r); + NumObj *sub(NumObj *r); + NumObj *mul(NumObj *r); NumObj *div(NumObj *r); bool lt(NumObj *r); bool gt(NumObj *r); @@ -209,7 +221,7 @@ class SpecialOptQuote: public SpecialOptObj { BUILTIN_PROC_DEF(num_add); BUILTIN_PROC_DEF(num_sub); -BUILTIN_PROC_DEF(num_multi); +BUILTIN_PROC_DEF(num_mul); BUILTIN_PROC_DEF(num_div); BUILTIN_PROC_DEF(num_lt); diff --git a/eval.cpp b/eval.cpp index de43fe8..f05eae0 100644 --- a/eval.cpp +++ b/eval.cpp @@ -24,7 +24,7 @@ void Evaluator::add_builtin_routines() { ADD_BUILTIN_PROC("+", num_add); ADD_BUILTIN_PROC("-", num_sub); - ADD_BUILTIN_PROC("*", num_multi); + ADD_BUILTIN_PROC("*", num_mul); ADD_BUILTIN_PROC("/", num_div); ADD_BUILTIN_PROC("<", num_lt); diff --git a/model.h b/model.h index 5a4800c..4522b89 100644 --- a/model.h +++ b/model.h @@ -311,9 +311,9 @@ class NumObj: public EvalObj { NumObj(NumLvl level, bool _exactness); bool is_exact(); virtual NumObj *convert(NumObj *r) = 0; - virtual NumObj *plus(NumObj *r) = 0; - virtual NumObj *minus(NumObj *r) = 0; - virtual NumObj *multi(NumObj *r) = 0; + virtual NumObj *add(NumObj *r) = 0; + virtual NumObj *sub(NumObj *r) = 0; + virtual NumObj *mul(NumObj *r) = 0; virtual NumObj *div(NumObj *r) = 0; virtual bool lt(NumObj *r) = 0; virtual bool gt(NumObj *r) = 0; -- cgit v1.2.3-70-g09d2