diff options
author | Teddy <[email protected]> | 2013-08-13 14:34:15 +0800 |
---|---|---|
committer | Teddy <[email protected]> | 2013-08-13 14:34:15 +0800 |
commit | bac19b8e0e820ef748439891f6bbd46aabb4fcf7 (patch) | |
tree | 79cf4d7629ae3870375f71949cda5679196677e3 | |
parent | 283cc828e86a7177edbacfe3860ca7765661f811 (diff) |
in-place arithmetic opt & fix gc bug in `eval`
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | builtin.cpp | 210 | ||||
-rw-r--r-- | eval.cpp | 1 | ||||
-rw-r--r-- | gc.cpp | 7 | ||||
-rw-r--r-- | types.cpp | 190 | ||||
-rw-r--r-- | types.h | 67 |
6 files changed, 303 insertions, 174 deletions
@@ -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; } @@ -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(); } } } @@ -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 } @@ -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) { @@ -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); |