aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-07 15:43:54 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-07 15:43:54 +0800
commite0c274fc6b7dc1c500ceb1375c2a8c4a09c1018c (patch)
treef0cfe8958b20a3516797762ea3015c1a17341a25
parent8a92faf9f1e9f77e05db7dc8a1399317ba530f93 (diff)
added GMP support
-rw-r--r--Makefile4
-rw-r--r--TODO.rst1
-rw-r--r--builtin.cpp152
-rw-r--r--builtin.h40
-rw-r--r--eval.cpp2
-rw-r--r--model.h6
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<RatNumObj*>(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<IntNumObj*>(obj)->val, 0);
+#else
+ return new CompNumObj(static_cast<IntNumObj*>(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<CompNumObj*>(_r);
return new CompNumObj(A + C, B + D);
}
-NumObj *CompNumObj::minus(NumObj *_r) {
+NumObj *CompNumObj::sub(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_r);
return new CompNumObj(A - C, B - D);
}
-NumObj *CompNumObj::multi(NumObj *_r) {
+NumObj *CompNumObj::mul(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_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<RatNumObj*>(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<IntNumObj*>(obj)->val);
+#else
+ return new RealNumObj(static_cast<IntNumObj*>(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<RealNumObj*>(_r)->real);
}
-NumObj *RealNumObj::minus(NumObj *_r) {
+NumObj *RealNumObj::sub(NumObj *_r) {
return new RealNumObj(real - static_cast<RealNumObj*>(_r)->real);
}
-NumObj *RealNumObj::multi(NumObj *_r) {
+NumObj *RealNumObj::mul(NumObj *_r) {
return new RealNumObj(real * static_cast<RealNumObj*>(_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<RatNumObj*>(obj); break;
case NUM_LVL_INT:
+#ifndef GMP_SUPPORT
return new RatNumObj(static_cast<IntNumObj*>(obj)->val, 1);
+#else
+ return new RatNumObj(mpq_class(
+ static_cast<IntNumObj*>(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<RatNumObj*>(_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<RatNumObj*>(_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<RatNumObj*>(_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<RatNumObj*>(_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<RatNumObj*>(_r);
+#ifndef GMP_SUPPORT
return A * D < C * B;
+#else
+ return val < r->val;
+#endif
}
bool RatNumObj::gt(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_r);
+#ifndef GMP_SUPPORT
return A * D > C * B;
+#else
+ return val > r->val;
+#endif
}
bool RatNumObj::eq(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_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<IntNumObj*>(_r)->val);
}
-NumObj *IntNumObj::minus(NumObj *_r) {
+NumObj *IntNumObj::sub(NumObj *_r) {
return new IntNumObj(val - static_cast<IntNumObj*>(_r)->val);
}
-NumObj *IntNumObj::multi(NumObj *_r) {
+NumObj *IntNumObj::mul(NumObj *_r) {
return new IntNumObj(val * static_cast<IntNumObj*>(_r)->val);
}
NumObj *IntNumObj::div(NumObj *_r) {
- return new IntNumObj(val / static_cast<IntNumObj*>(_r)->val);
+#ifndef GMP_SUPPORT
+ return new RatNumObj(val, static_cast<IntNumObj*>(_r)->val);
+#else
+ return new RatNumObj(mpq_class(val,
+ static_cast<IntNumObj*>(_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 <string>
+#include <gmpxx.h>
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;