mirror of
https://github.com/louisrubet/rpn
synced 2024-12-27 09:58:56 +01:00
#148: arbitrary base real entry, command base
This commit is contained in:
parent
3be884c4e3
commit
c095d9978c
8 changed files with 128 additions and 17 deletions
17
MANUAL.md
17
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue