From c095d9978c6b8be876f74c016ab9fa5f9b755974 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 1 Jul 2017 00:25:41 +0200 Subject: [PATCH] #148: arbitrary base real entry, command base --- MANUAL.md | 17 ++++++----- src/constant.h | 4 +++ src/object.cpp | 4 +++ src/object.hpp | 8 +++-- src/parse.hpp | 31 +++++++++++++++----- src/program.cpp | 1 + src/rpn-real.hpp | 14 +++++++++ test/11-base-entry.txt | 66 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 128 insertions(+), 17 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 9935b77..514e84f 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -63,14 +63,14 @@ rpn> ``` rpn> -Display all 144 possibilities? (y or n) -nop exit chs sqrt sign floor im std > or dropn depth num end do sto sto- pi d->r alog10 cosh -help test neg sq % ceil conj fix >= xor erase roll size start until rcl sto* sin r->d exp10 acosh -h version * sqr %CH ip arg sci < not rot rolld pos for unti purge sto/ asin e log2 tanh -? uname / abs mod fp c->r prec <= same dup over sub next while vars sneg cos ln alog2 atanh -q history inv dec fact min r->c round != swap dup2 ->str if step whil clusr sinv acos log exp2 -quit + ^ hex mant max p->r default == drop dupn str-> then ift repeat edit eval tan exp sinh -q - pow bin xpon re r->p type and drop2 pick chr else ifte repea sto+ -> atan log10 asinh +Display all 145 possibilities? (y or n) +nop exit chs sqrt base xpon re r->p type and drop2 pick chr else ifte repea sto+ -> atan log10 asinh +help test neg sq sign floor im std > or dropn depth num end do sto sto- pi d->r alog10 cosh +h version * sqr % ceil conj fix >= xor erase roll size start until rcl sto* sin r->d exp10 acosh +? uname / abs %CH ip arg sci < not rot rolld pos for unti purge sto/ asin e log2 tanh +q history inv dec mod fp c->r prec <= same dup over sub next while vars sneg cos ln alog2 atanh +quit + ^ hex fact min r->c round != swap dup2 ->str if step whil clusr sinv acos log exp2 +q - pow bin mant max p->r default == drop dupn str-> then ift repeat edit eval tan exp sinh rpn> ``` @@ -104,6 +104,7 @@ rpn> |`dec`| decimal representation |`hex`| hexadecimal representation |`bin`| binary representation +|`base`| arbitrary base representation |`sign`| sign of a real, unary vector in the same direction for a complex ### operations on reals diff --git a/src/constant.h b/src/constant.h index 7efb322..43684fc 100644 --- a/src/constant.h +++ b/src/constant.h @@ -76,6 +76,10 @@ typedef enum { #define HISTORY_FILE ".rpn_history" #define HISTORY_FILE_MAX_LINES (100) +// base min and max +#define BASE_MIN 2 +#define BASE_MAX 62 + // some defs for mpfr #if _MPFR_EXP_FORMAT == 1 #define MPFR_EXP_MAX (SHRT_MAX) diff --git a/src/object.cpp b/src/object.cpp index a94a10b..d9f4a73 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -195,6 +195,10 @@ void object::show(FILE* stream) fprintf(stream, "0b"); print_fix(stream, ((number*)this)->_value.mpfr, 2); break; + case number::base: + fprintf(stream, "%db", ((number*)this)->_base); + print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base); + break; default: fprintf(stream, ""); break; diff --git a/src/object.hpp b/src/object.hpp index b17a1ed..a4bfc68 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -44,7 +44,7 @@ struct floating_t void move() { void* significand = (void*)(this+1); - mpfr->_mpfr_d = (mp_limb_t*)significand; + mpfr_custom_move(mpfr, significand); } floating_t& operator=(const double val) @@ -119,8 +119,12 @@ struct number : public object enum { dec, hex, - bin + bin, + base } _representation; + // base + // carefull: _base is used only if _representation = base + int _base; // mind that float value is at the end of the object // because its mantissa is just after the obj in memory floating_t _value; diff --git a/src/parse.hpp b/src/parse.hpp index ec31340..3e9cb35 100644 --- a/src/parse.hpp +++ b/src/parse.hpp @@ -403,7 +403,7 @@ static bool get_program(string& entry, program& prog, string& remaining_entry) return ret; } -static bool get_number(const string& entry, program& prog, string& remaining_entry) +static bool get_number(string& entry, program& prog, string& remaining_entry) { char* endptr; bool ret = false; @@ -411,20 +411,37 @@ static bool get_number(const string& entry, program& prog, string& remaining_ent if (entry.size() > 0) { // pre parse to avoid doing a useless allocation - // detect the begining of a number, including nan, inf, @nan@, @inf@ + // detect the begining of a number including nan, inf, @nan@, @inf@ if (entry.find_first_of("+-0123456789.ni@", 0) == 0) { + // detect an arbitrary base entry like 3bXXX or 27bYYY + int base = 0; + size_t base_detect = entry.find_first_of("b", 0); + if (base_detect == 1 || base_detect == 2) + if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62) + entry=entry.substr(base_detect+1); + else + base = 0; + number* num = (number*)prog.allocate_back(number::calc_size(), cmd_number); - int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, 0, MPFR_DEFAULT_RND); + int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, base, MPFR_DEFAULT_RND); if (endptr != NULL && endptr != entry.c_str()) { // determine representation - string beg = entry.substr(0, 2); - if (beg == "0x" || beg == "0X") - num->_representation = number::hex; + if (base != 0) + { + num->_representation = number::base; + num->_base = base; + } else - num->_representation = number::dec; + { + string beg = entry.substr(0, 2); + if (beg == "0x" || beg == "0X") + num->_representation = number::hex; + else + num->_representation = number::dec; + } ret = true; diff --git a/src/program.cpp b/src/program.cpp index 33df7bf..a4a9895 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -39,6 +39,7 @@ program::keyword_t program::s_keywords[] = { cmd_keyword, "dec", &program::dec, "decimal representation" }, { cmd_keyword, "hex", &program::hex, "hexadecimal representation" }, { cmd_keyword, "bin", &program::bin, "decimal representation" }, + { cmd_keyword, "base", &program::base, "arbitrary base representation" }, { cmd_keyword, "sign", &program::sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0" }, //OPERATIONS ON REALS diff --git a/src/rpn-real.hpp b/src/rpn-real.hpp index 67c3ec3..36f3971 100644 --- a/src/rpn-real.hpp +++ b/src/rpn-real.hpp @@ -444,6 +444,20 @@ void dec() ((number*)_stack->back())->_representation = number::dec; } +void base() +{ + MIN_ARGUMENTS(2); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(1, cmd_number); + if (mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MIN) >= 0 && mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MAX) <= 0) + { + ((number*)_stack->get_obj(1))->_representation = number::base; + ((number*)_stack->get_obj(1))->_base = (int)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); + } + else + ERR_CONTEXT(ret_out_of_range); +} + void fact() { MIN_ARGUMENTS(1); diff --git a/test/11-base-entry.txt b/test/11-base-entry.txt index 80253e6..86d1443 100644 --- a/test/11-base-entry.txt +++ b/test/11-base-entry.txt @@ -98,3 +98,69 @@ erase default 12.34 bin -> stack should be 0b1100 erase default + +# base entry (1) +3b111 dup dec +-> stack should be 3b111, 13 +erase default + +# base entry (2) +3b114 +-> stack should be 3b11, 4 +erase default + +# base entry (3) +1b0 +-> stack should be 1, 'b0' +erase default + +# base entry (4) +62b20 dup dec +-> stack should be 62b20, 124 +erase default + +# base entry (5) +63b20 +-> stack should be 63, 'b20' +erase default + +# base entry (6) +2b11001100 0b11001100 == +-> stack should be 2b1 +erase default + +# base entry (7) +10b1234 1234 == +-> stack should be 10b1 +erase default + +# base entry (8) +16b1234 0x1234 == +-> stack should be 16b1 +erase default + +# base display (1) +2 62 for i 62 i base next +-> stack should be 2b111110, 3b2022, 4b332, 5b222, 6b142, 7b116, 8b76, 9b68, 10b62, 11b57, 12b52, 13b4a, 14b46, 15b42, 16b3e, 17b3b, 18b38, 19b35, 20b32, 21b2k, 22b2i, 23b2g, 24b2e, 25b2c, 26b2a, 27b28, 28b26, 29b24, 30b22, 31b20, 32b1u, 33b1t, 34b1s, 35b1r, 36b1q, 37b1P, 38b1O, 39b1N, 40b1M, 41b1L, 42b1K, 43b1J, 44b1I, 45b1H, 46b1G, 47b1F, 48b1E, 49b1D, 50b1C, 51b1B, 52b1A, 53b19, 54b18, 55b17, 56b16, 57b15, 58b14, 59b13, 60b12, 61b11, 62b10 +erase default + +# base display (2) +2 62 for i i 62 base next +-> stack should be 62b2, 62b3, 62b4, 62b5, 62b6, 62b7, 62b8, 62b9, 62bA, 62bB, 62bC, 62bD, 62bE, 62bF, 62bG, 62bH, 62bI, 62bJ, 62bK, 62bL, 62bM, 62bN, 62bO, 62bP, 62bQ, 62bR, 62bS, 62bT, 62bU, 62bV, 62bW, 62bX, 62bY, 62bZ, 62ba, 62bb, 62bc, 62bd, 62be, 62bf, 62bg, 62bh, 62bi, 62bj, 62bk, 62bl, 62bm, 62bn, 62bo, 62bp, 62bq, 62br, 62bs, 62bt, 62bu, 62bv, 62bw, 62bx, 62by, 62bz, 62b10 +erase default + +# base display (3) +100 dup 3 base == +13455600 dup 5 base == +55756 dup 17 base == +2345321 dup 62 base == +-> stack should be 1, 1, 1, 1 +erase default + +# base display (4) +100 18 base dup 3 base == dec +13455600 55 base dup 5 base == dec +55756 9 base dup 17 base == dec +2345321 57 base dup 62 base == dec +-> stack should be 1, 1, 1, 1 +erase default