#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>
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

View file

@ -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)

View file

@ -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, "<unknown number representation>");
break;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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