aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-13 14:34:15 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-13 14:34:15 +0800
commitbac19b8e0e820ef748439891f6bbd46aabb4fcf7 (patch)
tree79cf4d7629ae3870375f71949cda5679196677e3
parent283cc828e86a7177edbacfe3860ca7765661f811 (diff)
in-place arithmetic opt & fix gc bug in `eval`
-rw-r--r--Makefile2
-rw-r--r--builtin.cpp210
-rw-r--r--eval.cpp1
-rw-r--r--gc.cpp7
-rw-r--r--types.cpp190
-rw-r--r--types.h67
6 files changed, 303 insertions, 174 deletions
diff --git a/Makefile b/Makefile
index ee70498..ce8a500 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ sonsi: main.o parser.o builtin.o model.o eval.o exc.o consts.o types.o gc.o
g++ -o sonsi $^ -pg -lgmp
.cpp.o:
- g++ $< -c -g -DGMP_SUPPORT -Wall -DGC_INFO -O2
+ g++ $< -c -O2 -DGMP_SUPPORT -Wall
clean:
rm -f *.o
diff --git a/builtin.cpp b/builtin.cpp
index dc1c5c9..7a4a78a 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -333,6 +333,7 @@ Pair *SpecialOptEval::call(Pair *args, Environment * &envt,
Pair *ret_addr = ret_info->addr;
if (ret_info->state)
{
+ gc.expose(ret_info->state); // Exec done
delete *top_ptr;
*top_ptr++ = gc.attach(TO_PAIR(args->cdr)->car);
gc.expose(args);
@@ -343,6 +344,7 @@ Pair *SpecialOptEval::call(Pair *args, Environment * &envt,
gc.attach(static_cast<EvalObj*>(*(++top_ptr)));
top_ptr++;
ret_info->state = TO_PAIR(args->cdr);
+ gc.attach(ret_info->state); // Or it will be released
ret_info->state->next = NULL;
gc.expose(args);
return ret_info->state;
@@ -620,7 +622,7 @@ BUILTIN_PROC_DEF(pair_cdr) {
BUILTIN_PROC_DEF(make_list) {
- return args;
+ return gc.attach(args); // Or it will be GCed
}
BUILTIN_PROC_DEF(num_add) {
@@ -632,11 +634,16 @@ BUILTIN_PROC_DEF(num_add) {
throw TokenError("a number", RUN_ERR_WRONG_TYPE);
opr = static_cast<NumObj*>(args->car);
NumObj *_res = res;
- if (_res->level < opr->level)
- opr = _res->convert(opr);
+ if (res->level < opr->level)
+ {
+ res->add(opr = res->convert(opr));
+ delete opr;
+ }
else
- _res = opr->convert(_res);
- res = _res->add(opr);
+ {
+ (res = opr->convert(res))->add(opr);
+ delete _res;
+ }
}
return res;
}
@@ -647,12 +654,15 @@ BUILTIN_PROC_DEF(num_sub) {
throw TokenError("a number", RUN_ERR_WRONG_TYPE);
NumObj *res = static_cast<NumObj*>(args->car), *opr;
+ res = res->clone();
args = TO_PAIR(args->cdr);
if (args == empty_list)
{
- IntNumObj _zero(0);
- NumObj *zero = res->convert(&_zero);
- return zero->sub(res);
+ IntNumObj *_zero = new IntNumObj(0);
+ NumObj *zero = res->convert(_zero);
+ if (zero != _zero) delete _zero;
+ zero->sub(res);
+ return zero;
}
for (; args != empty_list; args = TO_PAIR(args->cdr))
{
@@ -661,16 +671,20 @@ BUILTIN_PROC_DEF(num_sub) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
NumObj *_res = res;
- if (_res->level < opr->level)
- opr = _res->convert(opr);
+ if (res->level < opr->level)
+ {
+ res->sub(opr = res->convert(opr));
+ delete opr;
+ }
else
- _res = opr->convert(_res);
- res = _res->sub(opr);
+ {
+ (res = opr->convert(res))->sub(opr);
+ delete _res;
+ }
}
return res;
}
-
BUILTIN_PROC_DEF(num_mul) {
// ARGS_AT_LEAST_ONE;
NumObj *res = new IntNumObj(1), *opr; // the most accurate type
@@ -680,11 +694,16 @@ BUILTIN_PROC_DEF(num_mul) {
throw TokenError("a number", RUN_ERR_WRONG_TYPE);
opr = static_cast<NumObj*>(args->car);
NumObj *_res = res;
- if (_res->level < opr->level)
- opr = _res->convert(opr);
+ if (res->level < opr->level)
+ {
+ res->mul(opr = res->convert(opr));
+ delete opr;
+ }
else
- _res = opr->convert(_res);
- res = _res->mul(opr);
+ {
+ (res = opr->convert(res))->mul(opr);
+ delete _res;
+ }
}
return res;
}
@@ -693,13 +712,20 @@ BUILTIN_PROC_DEF(num_div) {
ARGS_AT_LEAST_ONE;
if (!args->car->is_num_obj())
throw TokenError("a number", RUN_ERR_WRONG_TYPE);
+
NumObj *res = static_cast<NumObj*>(args->car), *opr;
+ if (res->level > NUM_LVL_RAT)
+ res = new RatNumObj(static_cast<IntNumObj*>(res)->val);
+ else res = res->clone();
+
args = TO_PAIR(args->cdr);
if (args == empty_list)
{
- IntNumObj _one(1);
- NumObj *one = res->convert(&_one);
- return one->div(res);
+ IntNumObj *_one = new IntNumObj(1);
+ NumObj *one = res->convert(_one);
+ if (one != _one) delete _one;
+ one->div(res);
+ return one;
}
for (; args != empty_list; args = TO_PAIR(args->cdr))
{
@@ -708,15 +734,21 @@ BUILTIN_PROC_DEF(num_div) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
NumObj *_res = res;
- if (_res->level < opr->level)
- opr = _res->convert(opr);
+ if (res->level < opr->level)
+ {
+ res->div(opr = res->convert(opr));
+ delete opr;
+ }
else
- _res = opr->convert(_res);
- res = _res->div(opr);
+ {
+ (res = opr->convert(res))->div(opr);
+ delete _res;
+ }
}
return res;
}
+
BUILTIN_PROC_DEF(num_le) {
if (args == empty_list)
return new BoolObj(true);
@@ -733,16 +765,28 @@ BUILTIN_PROC_DEF(num_le) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
if (last->level < opr->level)
- opr = last->convert(opr);
+ {
+ if (!last->le(opr = last->convert(opr)))
+ {
+ delete opr;
+ return new BoolObj(false);
+ }
+ else delete opr;
+ }
else
- last = opr->convert(last);
- if (!last->le(opr))
- return new BoolObj(false);
+ {
+ if (!(last = opr->convert(last))->le(opr))
+ {
+ delete last;
+ return new BoolObj(false);
+ }
+ else delete last;
+ }
}
return new BoolObj(true);
}
-BUILTIN_PROC_DEF(num_ge) {
+BUILTIN_PROC_DEF(num_lt) {
if (args == empty_list)
return new BoolObj(true);
// zero arguments
@@ -758,17 +802,28 @@ BUILTIN_PROC_DEF(num_ge) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
if (last->level < opr->level)
- opr = last->convert(opr);
+ {
+ if (!last->lt(opr = last->convert(opr)))
+ {
+ delete opr;
+ return new BoolObj(false);
+ }
+ else delete opr;
+ }
else
- last = opr->convert(last);
- if (!last->ge(opr))
- return new BoolObj(false);
+ {
+ if (!(last = opr->convert(last))->lt(opr))
+ {
+ delete last;
+ return new BoolObj(false);
+ }
+ else delete last;
+ }
}
return new BoolObj(true);
}
-
-BUILTIN_PROC_DEF(num_lt) {
+BUILTIN_PROC_DEF(num_ge) {
if (args == empty_list)
return new BoolObj(true);
// zero arguments
@@ -784,11 +839,23 @@ BUILTIN_PROC_DEF(num_lt) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
if (last->level < opr->level)
- opr = last->convert(opr);
+ {
+ if (!last->ge(opr = last->convert(opr)))
+ {
+ delete opr;
+ return new BoolObj(false);
+ }
+ else delete opr;
+ }
else
- last = opr->convert(last);
- if (!last->lt(opr))
- return new BoolObj(false);
+ {
+ if (!(last = opr->convert(last))->ge(opr))
+ {
+ delete last;
+ return new BoolObj(false);
+ }
+ else delete last;
+ }
}
return new BoolObj(true);
}
@@ -809,11 +876,23 @@ BUILTIN_PROC_DEF(num_gt) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
if (last->level < opr->level)
- opr = last->convert(opr);
+ {
+ if (!last->gt(opr = last->convert(opr)))
+ {
+ delete opr;
+ return new BoolObj(false);
+ }
+ else delete opr;
+ }
else
- last = opr->convert(last);
- if (!last->gt(opr))
- return new BoolObj(false);
+ {
+ if (!(last = opr->convert(last))->gt(opr))
+ {
+ delete last;
+ return new BoolObj(false);
+ }
+ else delete last;
+ }
}
return new BoolObj(true);
}
@@ -834,15 +913,28 @@ BUILTIN_PROC_DEF(num_eq) {
opr = static_cast<NumObj*>(args->car);
// upper type conversion
if (last->level < opr->level)
- opr = last->convert(opr);
+ {
+ if (!last->eq(opr = last->convert(opr)))
+ {
+ delete opr;
+ return new BoolObj(false);
+ }
+ else delete opr;
+ }
else
- last = opr->convert(last);
- if (!last->eq(opr))
- return new BoolObj(false);
+ {
+ if (!(last = opr->convert(last))->eq(opr))
+ {
+ delete last;
+ return new BoolObj(false);
+ }
+ else delete last;
+ }
}
return new BoolObj(true);
}
+
BUILTIN_PROC_DEF(bool_not) {
ARGS_EXACTLY_ONE;
return new BoolObj(!args->car->is_true());
@@ -1206,7 +1298,9 @@ BUILTIN_PROC_DEF(is_integer) {
BUILTIN_PROC_DEF(num_abs) {
ARGS_EXACTLY_ONE;
CHECK_NUMBER(args->car);
- return static_cast<NumObj*>(args->car)->abs();
+ NumObj* num = static_cast<NumObj*>(args->car)->clone();
+ num->abs();
+ return num;
}
BUILTIN_PROC_DEF(num_mod) {
@@ -1217,7 +1311,9 @@ BUILTIN_PROC_DEF(num_mod) {
NumObj* b = static_cast<NumObj*>(TO_PAIR(args->cdr)->car);
CHECK_INT(a);
CHECK_INT(b);
- return static_cast<IntNumObj*>(a)->mod(b);
+ NumObj* res = a->clone();
+ static_cast<IntNumObj*>(res)->mod(b);
+ return res;
}
BUILTIN_PROC_DEF(num_rem) {
@@ -1228,7 +1324,9 @@ BUILTIN_PROC_DEF(num_rem) {
NumObj* b = static_cast<NumObj*>(TO_PAIR(args->cdr)->car);
CHECK_INT(a);
CHECK_INT(b);
- return static_cast<IntNumObj*>(a)->rem(b);
+ NumObj* res = a->clone();
+ static_cast<IntNumObj*>(res)->rem(b);
+ return res;
}
BUILTIN_PROC_DEF(num_quo) {
@@ -1239,12 +1337,14 @@ BUILTIN_PROC_DEF(num_quo) {
NumObj* b = static_cast<NumObj*>(TO_PAIR(args->cdr)->car);
CHECK_INT(a);
CHECK_INT(b);
- return static_cast<IntNumObj*>(a)->quo(b);
+ NumObj* res = a->clone();
+ static_cast<IntNumObj*>(res)->div(b);
+ return res;
}
BUILTIN_PROC_DEF(num_gcd) {
// ARGS_AT_LEAST_ONE;
- NumObj *res = new IntNumObj(0);
+ IntNumObj *res = new IntNumObj(0);
IntNumObj *opr;
for (;args != empty_list; args = TO_PAIR(args->cdr))
{
@@ -1252,14 +1352,14 @@ BUILTIN_PROC_DEF(num_gcd) {
CHECK_INT(static_cast<NumObj*>(args->car));
opr = static_cast<IntNumObj*>(args->car);
- res = opr->gcd(res);
+ res->gcd(opr);
}
return res;
}
BUILTIN_PROC_DEF(num_lcm) {
// ARGS_AT_LEAST_ONE;
- NumObj *res = new IntNumObj(1);
+ IntNumObj *res = new IntNumObj(1);
IntNumObj *opr;
for (;args != empty_list; args = TO_PAIR(args->cdr))
{
@@ -1267,7 +1367,7 @@ BUILTIN_PROC_DEF(num_lcm) {
CHECK_INT(static_cast<NumObj*>(args->car));
opr = static_cast<IntNumObj*>(args->car);
- res = opr->lcm(res);
+ res->lcm(opr);
}
return res;
}
diff --git a/eval.cpp b/eval.cpp
index 73c2120..bf61b3e 100644
--- a/eval.cpp
+++ b/eval.cpp
@@ -204,6 +204,7 @@ EvalObj *Evaluator::run_expr(Pair *prog) {
call(args, envt, cont, top_ptr);
else
throw TokenError(opt->ext_repr(), SYN_ERR_CAN_NOT_APPLY);
+ gc.force();
}
}
}
diff --git a/gc.cpp b/gc.cpp
index 4b6eaca..54248c3 100644
--- a/gc.cpp
+++ b/gc.cpp
@@ -48,13 +48,13 @@ void GarbageCollector::force() {
} // fetch the pending pointers in the list
// clear the list
pending_list = NULL; */
- fprintf(stderr, "%ld\n", mapping.size());
for (EvalObj2Int::iterator it = mapping.begin();
it != mapping.end(); it++)
if (it->second == 0) *r++ = it->first;
collecting = true;
#ifdef GC_INFO
+ fprintf(stderr, "%ld\n", mapping.size());
size_t cnt = 0;
#endif
#ifdef GC_DEBUG
@@ -91,9 +91,10 @@ void GarbageCollector::force() {
#endif
#ifdef GC_DEBUG
- for (EvalObj2Int::iterator it = mapping.begin();
+/* for (EvalObj2Int::iterator it = mapping.begin();
it != mapping.end(); it++)
fprintf(stderr, "%llx => %s\n", (ull)it->first, it->first->ext_repr().c_str());
+ */
#endif
collecting = false;
}
@@ -107,7 +108,7 @@ EvalObj *GarbageCollector::attach(EvalObj *ptr) {
fprintf(stderr, "GC: 0x%llx attached. count = %lu \"%s\"\n",
(ull)ptr, mapping[ptr], ptr->ext_repr().c_str());
#endif
- if (mapping.size() > GC_QUEUE_SIZE >> 1)
+ if (mapping.size() > GC_QUEUE_SIZE >> 2)
force();
return ptr; // passing through
}
diff --git a/types.cpp b/types.cpp
index 8ccf2ab..6a24239 100644
--- a/types.cpp
+++ b/types.cpp
@@ -521,11 +521,16 @@ CompNumObj::CompNumObj(double _real, double _imag) :
return new CompNumObj(real, imag);
}
+NumObj *CompNumObj::clone() const {
+ return new CompNumObj(*this);
+}
+
CompNumObj *CompNumObj::convert(NumObj *obj) {
switch (obj->level)
{
case NUM_LVL_COMP :
- return static_cast<CompNumObj*>(obj); break;
+ return new CompNumObj(*static_cast<CompNumObj*>(obj));
+ break;
case NUM_LVL_REAL :
return new CompNumObj(static_cast<RealNumObj*>(obj)->real, 0);
break;
@@ -554,30 +559,32 @@ CompNumObj *CompNumObj::convert(NumObj *obj) {
#define C (r->real)
#define D (r->imag)
-NumObj *CompNumObj::add(NumObj *_r) {
+void CompNumObj::add(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_r);
- return new CompNumObj(A + C, B + D);
+ real += C;
+ imag += D;
}
-NumObj *CompNumObj::sub(NumObj *_r) {
+void CompNumObj::sub(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_r);
- return new CompNumObj(A - C, B - D);
+ real -= C;
+ imag -= D;
}
-NumObj *CompNumObj::mul(NumObj *_r) {
+void CompNumObj::mul(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_r);
- return new CompNumObj(A * C - B * D,
- B * C + A * D);
+ A = A * C - B * D;
+ B = B * C + A * D;
}
-NumObj *CompNumObj::div(NumObj *_r) {
+void CompNumObj::div(NumObj *_r) {
CompNumObj *r = static_cast<CompNumObj*>(_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);
+ A = (A * C + B * D) * f,
+ B = (B * C - A * D) * f;
}
bool NumObj::lt(NumObj *_r) {
@@ -596,7 +603,7 @@ bool NumObj::ge(NumObj *_r) {
throw TokenError("a comparable number", RUN_ERR_WRONG_TYPE);
}
-NumObj *NumObj::abs() {
+void NumObj::abs() {
throw TokenError("a real number", RUN_ERR_WRONG_TYPE);
}
@@ -618,6 +625,10 @@ ReprCons *CompNumObj::get_repr_cons() {
RealNumObj::RealNumObj(double _real) : InexactNumObj(NUM_LVL_REAL), real(_real) {}
+NumObj *RealNumObj::clone() const {
+ return new RealNumObj(*this);
+}
+
RealNumObj *RealNumObj::from_string(string repr) {
bool flag;
double real = str_to_double(repr, flag);
@@ -629,7 +640,8 @@ RealNumObj *RealNumObj::convert(NumObj *obj) {
switch (obj->level)
{
case NUM_LVL_REAL:
- return static_cast<RealNumObj*>(obj); break;
+ return new RealNumObj(*static_cast<RealNumObj*>(obj));
+ break;
case NUM_LVL_RAT:
{
RatNumObj *rat = static_cast<RatNumObj*>(obj);
@@ -651,24 +663,24 @@ RealNumObj *RealNumObj::convert(NumObj *obj) {
throw NormalError(INT_ERR);
}
-NumObj *RealNumObj::add(NumObj *_r) {
- return new RealNumObj(real + static_cast<RealNumObj*>(_r)->real);
+void RealNumObj::add(NumObj *_r) {
+ real += static_cast<RealNumObj*>(_r)->real;
}
-NumObj *RealNumObj::sub(NumObj *_r) {
- return new RealNumObj(real - static_cast<RealNumObj*>(_r)->real);
+void RealNumObj::sub(NumObj *_r) {
+ real -= static_cast<RealNumObj*>(_r)->real;
}
-NumObj *RealNumObj::mul(NumObj *_r) {
- return new RealNumObj(real * static_cast<RealNumObj*>(_r)->real);
+void RealNumObj::mul(NumObj *_r) {
+ real *= static_cast<RealNumObj*>(_r)->real;
}
-NumObj *RealNumObj::div(NumObj *_r) {
- return new RealNumObj(real / static_cast<RealNumObj*>(_r)->real);
+void RealNumObj::div(NumObj *_r) {
+ real /= static_cast<RealNumObj*>(_r)->real;
}
-NumObj *RealNumObj::abs() {
- return new RealNumObj(fabs(real));
+void RealNumObj::abs() {
+ real = fabs(real);
}
bool RealNumObj::eq(NumObj *_r) {
@@ -724,10 +736,13 @@ RatNumObj *RatNumObj::from_string(string repr) {
return new RatNumObj(a, b);
}
#else
-RatNumObj::RatNumObj(mpq_class _val) :
- ExactNumObj(NUM_LVL_RAT), val(_val) {
+RatNumObj::RatNumObj(mpq_class _val) : ExactNumObj(NUM_LVL_RAT), val(_val) {
val.canonicalize();
- }
+}
+
+NumObj *RatNumObj::clone() const {
+ return new RatNumObj(*this);
+}
RatNumObj *RatNumObj::from_string(string repr) {
try
@@ -743,6 +758,9 @@ RatNumObj *RatNumObj::from_string(string repr) {
return NULL;
}
}
+
+RatNumObj::RatNumObj(const RatNumObj &ori) :
+ ExactNumObj(NUM_LVL_RAT), val(ori.val.get_mpq_t()) {}
#endif
@@ -750,7 +768,8 @@ RatNumObj *RatNumObj::convert(NumObj *obj) {
switch (obj->level)
{
case NUM_LVL_RAT:
- return static_cast<RatNumObj*>(obj); break;
+ return new RatNumObj(*static_cast<RatNumObj*>(obj));
+ break;
case NUM_LVL_INT:
#ifndef GMP_SUPPORT
return new RatNumObj(static_cast<IntNumObj*>(obj)->val, 1);
@@ -768,55 +787,57 @@ RatNumObj *RatNumObj::convert(NumObj *obj) {
#define C (r->a)
#define D (r->b)
-NumObj *RatNumObj::add(NumObj *_r) {
+void RatNumObj::add(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_r);
#ifndef GMP_SUPPORT
- int na = A * D + B * C, nb = B * D;
+ A = A * D + B * C;
+ B = B * D;
int g = gcd(na, nb);
- na /= g;
- nb /= g;
- return new RatNumObj(na, nb);
+ A /= g;
+ B /= g;
#else
- return new RatNumObj(val + r->val);
+ val += r->val;
#endif
}
-NumObj *RatNumObj::sub(NumObj *_r) {
+void RatNumObj::sub(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_r);
#ifndef GMP_SUPPORT
- int na = A * D - B * C, nb = B * D;
+ A = A * D - B * C;
+ B = B * D;
int g = gcd(na, nb);
- na /= g;
- nb /= g;
- return new RatNumObj(na, nb);
+ A /= g;
+ B /= g;
#else
- return new RatNumObj(val - r->val);
+ val -= r->val;
#endif
}
-NumObj *RatNumObj::mul(NumObj *_r) {
+void RatNumObj::mul(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_r);
#ifndef GMP_SUPPORT
- int na = A * C, nb = B * D;
+ A = A * C;
+ B = B * D;
int g = gcd(na, nb);
- na /= g;
- nb /= g;
- return new RatNumObj(na, nb);
+ A /= g;
+ B /= g;
#else
- return new RatNumObj(val * r->val);
+ val *= r->val;
#endif
}
-NumObj *RatNumObj::div(NumObj *_r) {
+void RatNumObj::div(NumObj *_r) {
RatNumObj *r = static_cast<RatNumObj*>(_r);
#ifndef GMP_SUPPORT
- int na = A * D, nb = B * C;
+ A = A * D;
+ B = B * C;
int g = gcd(na, nb);
- na /= g;
- nb /= g;
- return new RatNumObj(na, nb);
+ A /= g;
+ B /= g;
#else
- return new RatNumObj(val / r->val);
+ if (r->val == 0)
+ throw NormalError(RUN_ERR_NUMERIC_OVERFLOW);
+ val /= r->val;
#endif
}
@@ -866,11 +887,11 @@ bool RatNumObj::eq(NumObj *_r) {
#endif
}
-NumObj *RatNumObj::abs() {
+void RatNumObj::abs() {
#ifndef GMP_SUPPORT
- return new RatNumObj((a > 0 ? a : -a), b);
+ if (a < 0) a = -a;
#else
- return new RatNumObj(std::abs(val));
+ val = ::abs(val);
#endif
}
@@ -885,6 +906,7 @@ ReprCons *RatNumObj::get_repr_cons() {
#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++)
@@ -910,75 +932,71 @@ IntNumObj *IntNumObj::from_string(string repr) {
}
}
int IntNumObj::get_i() { return val.get_si(); }
+IntNumObj::IntNumObj(const IntNumObj &ori) :
+ ExactNumObj(NUM_LVL_INT), val(ori.val.get_mpz_t()) {}
#endif
+
+NumObj *IntNumObj::clone() const {
+ return new IntNumObj(*this);
+}
+
IntNumObj *IntNumObj::convert(NumObj *obj) {
switch (obj->level)
{
case NUM_LVL_INT :
- return static_cast<IntNumObj*>(obj);
+ return new IntNumObj(*static_cast<IntNumObj*>(obj));
default:
throw NormalError(INT_ERR);
}
}
-NumObj *IntNumObj::add(NumObj *_r) {
- return new IntNumObj(val + static_cast<IntNumObj*>(_r)->val);
+void IntNumObj::add(NumObj *_r) {
+ val += static_cast<IntNumObj*>(_r)->val;
}
-NumObj *IntNumObj::sub(NumObj *_r) {
- return new IntNumObj(val - static_cast<IntNumObj*>(_r)->val);
+void IntNumObj::sub(NumObj *_r) {
+ val -= static_cast<IntNumObj*>(_r)->val;
}
-NumObj *IntNumObj::mul(NumObj *_r) {
- return new IntNumObj(val * static_cast<IntNumObj*>(_r)->val);
-}
-
-NumObj *IntNumObj::div(NumObj *_r) {
-#ifndef GMP_SUPPORT
- return new RatNumObj(val, static_cast<IntNumObj*>(_r)->val);
-#else
- mpz_class d(static_cast<IntNumObj*>(_r)->val);
- if (d == 0) throw NormalError(RUN_ERR_NUMERIC_OVERFLOW);
- return new RatNumObj(mpq_class(val, d));
-#endif
+void IntNumObj::mul(NumObj *_r) {
+ val *= static_cast<IntNumObj*>(_r)->val;
}
-NumObj *IntNumObj::abs() {
- return new IntNumObj(std::abs(val));
+void IntNumObj::abs() {
+ val = ::abs(val);
}
-NumObj *IntNumObj::rem(NumObj *_r) {
+void IntNumObj::rem(NumObj *_r) {
const mpz_class &rval(static_cast<IntNumObj*>(_r)->val);
if (rval == 0) throw NormalError(RUN_ERR_NUMERIC_OVERFLOW);
- return new IntNumObj(val % rval);
+ val %= rval;
}
-NumObj *IntNumObj::mod(NumObj *_r) {
+void IntNumObj::mod(NumObj *_r) {
const mpz_class &rval = static_cast<IntNumObj*>(_r)->val;
if (rval == 0) throw NormalError(RUN_ERR_NUMERIC_OVERFLOW);
- mpz_class ret = val % rval;
- if (ret != 0 && sgn(ret) != sgn(rval))
- ret = ret + rval;
- return new IntNumObj(ret);
+ val %= rval;
+ if (val != 0 && sgn(val) != sgn(rval))
+ val += rval;
}
-NumObj *IntNumObj::quo(NumObj *_r) {
+void IntNumObj::div(NumObj *_r) {
const mpz_class &rval = static_cast<IntNumObj*>(_r)->val;
if (rval == 0) throw NormalError(RUN_ERR_NUMERIC_OVERFLOW);
- return new IntNumObj(val / rval);
+ val /= rval;
}
-NumObj *IntNumObj::gcd(NumObj *_r) {
+void IntNumObj::gcd(NumObj *_r) {
mpz_t g;
mpz_gcd(g, val.get_mpz_t(), static_cast<IntNumObj*>(_r)->val.get_mpz_t());
- return new IntNumObj(mpz_class(g));
+ val = mpz_class(g);
}
-NumObj *IntNumObj::lcm(NumObj *_r) {
+void IntNumObj::lcm(NumObj *_r) {
mpz_t l;
mpz_lcm(l, val.get_mpz_t(), static_cast<IntNumObj*>(_r)->val.get_mpz_t());
- return new IntNumObj(mpz_class(l));
+ val = mpz_class(l);
}
bool IntNumObj::lt(NumObj *_r) {
diff --git a/types.h b/types.h
index 1519242..5147e2d 100644
--- a/types.h
+++ b/types.h
@@ -234,13 +234,14 @@ class NumObj: public EvalObj {/*{{{*/
* Construct a general Numeric object
*/
NumObj(NumLvl level, bool _exactness);
+ virtual NumObj *clone() const = 0;
bool is_exact();
virtual NumObj *convert(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 NumObj *abs();
+ virtual void add(NumObj *r) = 0;
+ virtual void sub(NumObj *r) = 0;
+ virtual void mul(NumObj *r) = 0;
+ virtual void div(NumObj *r) = 0;
+ virtual void abs();
virtual bool lt(NumObj *r);
virtual bool gt(NumObj *r);
@@ -393,6 +394,7 @@ class CompNumObj: public InexactNumObj {/*{{{*/
/** Construct a complex number */
CompNumObj(double _real, double _imag);
+ NumObj *clone() const;
/** Try to construct an CompNumObj object
* @return NULL if failed
*/
@@ -400,10 +402,10 @@ class CompNumObj: public InexactNumObj {/*{{{*/
/** Convert to a complex number from other numeric types */
CompNumObj *convert(NumObj* obj);
- NumObj *add(NumObj *r);
- NumObj *sub(NumObj *r);
- NumObj *mul(NumObj *r);
- NumObj *div(NumObj *r);
+ void add(NumObj *r);
+ void sub(NumObj *r);
+ void mul(NumObj *r);
+ void div(NumObj *r);
bool eq(NumObj *r);
ReprCons *get_repr_cons();
};/*}}}*/
@@ -416,6 +418,7 @@ class RealNumObj: public InexactNumObj {/*{{{*/
double real;
/** Construct a real number */
RealNumObj(double _real);
+ NumObj *clone() const;
/** Try to construct an RealNumObj object
* @return NULL if failed
*/
@@ -423,11 +426,11 @@ class RealNumObj: public InexactNumObj {/*{{{*/
/** Convert to a real number from other numeric types */
RealNumObj *convert(NumObj* obj);
- NumObj *add(NumObj *r);
- NumObj *sub(NumObj *r);
- NumObj *mul(NumObj *r);
- NumObj *div(NumObj *r);
- NumObj *abs();
+ void add(NumObj *r);
+ void sub(NumObj *r);
+ void mul(NumObj *r);
+ void div(NumObj *r);
+ void abs();
bool lt(NumObj *r);
bool gt(NumObj *r);
bool le(NumObj *r);
@@ -458,7 +461,9 @@ class RatNumObj: public ExactNumObj {/*{{{*/
#else
mpq_class val;
RatNumObj(mpq_class val);
+ RatNumObj(const RatNumObj &ori);
#endif
+ NumObj *clone() const;
/** Try to construct an RatNumObj object
* @return NULL if failed
*/
@@ -466,11 +471,11 @@ class RatNumObj: public ExactNumObj {/*{{{*/
/** Convert to a Rational number from other numeric types */
RatNumObj *convert(NumObj* obj);
- NumObj *add(NumObj *r);
- NumObj *sub(NumObj *r);
- NumObj *mul(NumObj *r);
- NumObj *div(NumObj *r);
- NumObj *abs();
+ void add(NumObj *r);
+ void sub(NumObj *r);
+ void mul(NumObj *r);
+ void div(NumObj *r);
+ void abs();
bool lt(NumObj *r);
bool gt(NumObj *r);
bool le(NumObj *r);
@@ -494,7 +499,10 @@ class IntNumObj: public ExactNumObj {/*{{{*/
/** Construct a integer */
IntNumObj(mpz_class val);
int get_i();
+ /** Copy constructor */
+ IntNumObj(const IntNumObj &ori);
#endif
+ NumObj *clone() const;
/** Try to construct an IntNumObj object
* @return NULL if failed
*/
@@ -502,16 +510,17 @@ class IntNumObj: public ExactNumObj {/*{{{*/
/** Convert to a integer from other numeric types */
IntNumObj *convert(NumObj* obj);
- NumObj *add(NumObj *r);
- NumObj *sub(NumObj *r);
- NumObj *mul(NumObj *r);
- NumObj *div(NumObj *r);
- NumObj *abs();
- NumObj *mod(NumObj *r);
- NumObj *rem(NumObj *r);
- NumObj *quo(NumObj *r);
- NumObj *gcd(NumObj *r);
- NumObj *lcm(NumObj *r);
+ void add(NumObj *r);
+ void sub(NumObj *r);
+ void mul(NumObj *r);
+ void div(NumObj *r);
+ void abs();
+ void mod(NumObj *r);
+ void rem(NumObj *r);
+ void quo(NumObj *r);
+ void gcd(NumObj *r);
+ void lcm(NumObj *r);
+
bool lt(NumObj *r);
bool gt(NumObj *r);
bool le(NumObj *r);