#148: arbitrary base real entry, command base

This commit is contained in:
Louis Rubet 2017-07-01 00:25:41 +02:00
parent 3be884c4e3
commit c095d9978c
8 changed files with 128 additions and 17 deletions

View file

@ -63,14 +63,14 @@ rpn>
``` ```
rpn> rpn>
Display all 144 possibilities? (y or n) Display all 145 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 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 % ceil conj fix >= xor erase roll size start until rcl sto* sin r->d exp10 acosh help test neg sq sign floor im std > or dropn depth num end do sto sto- pi d->r alog10 cosh
h version * sqr %CH ip arg sci < not rot rolld pos for unti purge sto/ asin e log2 tanh h version * sqr % ceil conj fix >= xor erase roll size start until rcl sto* sin r->d exp10 acosh
? uname / abs mod fp c->r prec <= same dup over sub next while vars sneg cos ln alog2 atanh ? uname / abs %CH ip arg sci < not rot rolld pos for unti purge sto/ asin e log2 tanh
q history inv dec fact min r->c round != swap dup2 ->str if step whil clusr sinv acos log exp2 q history inv dec mod fp c->r prec <= same dup over sub next while vars sneg cos ln alog2 atanh
quit + ^ hex mant max p->r default == drop dupn str-> then ift repeat edit eval tan exp sinh quit + ^ hex fact min r->c round != swap dup2 ->str if step whil clusr sinv acos log exp2
q - pow bin xpon re r->p type and drop2 pick chr else ifte repea sto+ -> atan log10 asinh q - pow bin mant max p->r default == drop dupn str-> then ift repeat edit eval tan exp sinh
rpn> rpn>
``` ```
@ -104,6 +104,7 @@ rpn>
|`dec`| decimal representation |`dec`| decimal representation
|`hex`| hexadecimal representation |`hex`| hexadecimal representation
|`bin`| binary representation |`bin`| binary representation
|`base`| arbitrary base representation
|`sign`| sign of a real, unary vector in the same direction for a complex |`sign`| sign of a real, unary vector in the same direction for a complex
### operations on reals ### operations on reals

View file

@ -76,6 +76,10 @@ typedef enum {
#define HISTORY_FILE ".rpn_history" #define HISTORY_FILE ".rpn_history"
#define HISTORY_FILE_MAX_LINES (100) #define HISTORY_FILE_MAX_LINES (100)
// base min and max
#define BASE_MIN 2
#define BASE_MAX 62
// some defs for mpfr // some defs for mpfr
#if _MPFR_EXP_FORMAT == 1 #if _MPFR_EXP_FORMAT == 1
#define MPFR_EXP_MAX (SHRT_MAX) #define MPFR_EXP_MAX (SHRT_MAX)

View file

@ -195,6 +195,10 @@ void object::show(FILE* stream)
fprintf(stream, "0b"); fprintf(stream, "0b");
print_fix(stream, ((number*)this)->_value.mpfr, 2); print_fix(stream, ((number*)this)->_value.mpfr, 2);
break; break;
case number::base:
fprintf(stream, "%db", ((number*)this)->_base);
print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base);
break;
default: default:
fprintf(stream, "<unknown number representation>"); fprintf(stream, "<unknown number representation>");
break; break;

View file

@ -44,7 +44,7 @@ struct floating_t
void move() void move()
{ {
void* significand = (void*)(this+1); void* significand = (void*)(this+1);
mpfr->_mpfr_d = (mp_limb_t*)significand; mpfr_custom_move(mpfr, significand);
} }
floating_t& operator=(const double val) floating_t& operator=(const double val)
@ -119,8 +119,12 @@ struct number : public object
enum { enum {
dec, dec,
hex, hex,
bin bin,
base
} _representation; } _representation;
// base
// carefull: _base is used only if _representation = base
int _base;
// mind that float value is at the end of the object // mind that float value is at the end of the object
// because its mantissa is just after the obj in memory // because its mantissa is just after the obj in memory
floating_t _value; floating_t _value;

View file

@ -403,7 +403,7 @@ static bool get_program(string& entry, program& prog, string& remaining_entry)
return ret; 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; char* endptr;
bool ret = false; bool ret = false;
@ -411,20 +411,37 @@ static bool get_number(const string& entry, program& prog, string& remaining_ent
if (entry.size() > 0) if (entry.size() > 0)
{ {
// pre parse to avoid doing a useless allocation // 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) 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); 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()) if (endptr != NULL && endptr != entry.c_str())
{ {
// determine representation // determine representation
string beg = entry.substr(0, 2); if (base != 0)
if (beg == "0x" || beg == "0X") {
num->_representation = number::hex; num->_representation = number::base;
num->_base = base;
}
else 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; ret = true;

View file

@ -39,6 +39,7 @@ program::keyword_t program::s_keywords[] =
{ cmd_keyword, "dec", &program::dec, "decimal representation" }, { cmd_keyword, "dec", &program::dec, "decimal representation" },
{ cmd_keyword, "hex", &program::hex, "hexadecimal representation" }, { cmd_keyword, "hex", &program::hex, "hexadecimal representation" },
{ cmd_keyword, "bin", &program::bin, "decimal 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" }, { cmd_keyword, "sign", &program::sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0" },
//OPERATIONS ON REALS //OPERATIONS ON REALS

View file

@ -444,6 +444,20 @@ void dec()
((number*)_stack->back())->_representation = number::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() void fact()
{ {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);

View file

@ -98,3 +98,69 @@ erase default
12.34 bin 12.34 bin
-> stack should be 0b1100 -> stack should be 0b1100
erase default 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