mirror of
https://github.com/louisrubet/rpn
synced 2024-11-16 07:47:26 +01:00
#168: std is now unary and auto calcs its decimal digits nb, modified hel pmessage, added bounds check for precision in sci and fix
This commit is contained in:
parent
5033746821
commit
cdb129819d
8 changed files with 102 additions and 64 deletions
10
MANUAL.md
10
MANUAL.md
|
@ -37,9 +37,9 @@ rpn> 1.0986122886681096914
|
|||
### **arbitrary precision**
|
||||
Precision can be really high, up to 0x7FFFFFFFFFFFFFFF bits with GNU MPFR
|
||||
```
|
||||
rpn> 256 prec 200 std
|
||||
rpn> pi 3 * 4 / cos
|
||||
-0.707106781186547524400844362104849039284835937688474036588339868995366239(...)
|
||||
rpn> 256 prec
|
||||
rpn> pi
|
||||
3.1415926535897932384626433832795028841971693993751058209749445923078164062862
|
||||
rpn>
|
||||
```
|
||||
|
||||
|
@ -136,7 +136,7 @@ exit chs sqrt % ceil conj fix >= xor
|
|||
|
||||
|keyword|description|
|
||||
|-|-|
|
||||
|std| standard floating numbers representation. ex: [25] std
|
||||
|std| standard floating numbers representation. ex: std
|
||||
|fix| fixed point representation. ex: 6 fix
|
||||
|sci| scientific floating point representation. ex: 20 sci
|
||||
|prec| get float precision in bits when first stack is not a number, set float precision in bits when first stack entry is a number. ex: ```256 prec```
|
||||
|
@ -268,7 +268,7 @@ exit chs sqrt % ceil conj fix >= xor
|
|||
|
||||
### default
|
||||
|
||||
Default float mode is 'std' with 20 digits
|
||||
Default float mode is 'std' with 39 digits
|
||||
|
||||
Default floating point precision is 128 bits
|
||||
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
// default mode and number of printed digits
|
||||
//
|
||||
#define DEFAULT_MODE number::std
|
||||
#define DEFAULT_PRECISION 20
|
||||
#define MPFR_DEFAULT_FORMAT "%.20Rg"
|
||||
#define MPFR_DEFAULT_FORMAT "%.xxRg"
|
||||
|
||||
/* directly calculated from 128 bits precision
|
||||
ceil(128 * log10(2) = 39) */
|
||||
#define DEFAULT_DECIMAL_DIGITS 39
|
||||
|
||||
// MPFR related defaults
|
||||
//
|
||||
|
|
|
@ -12,7 +12,7 @@ const char* floating_t::s_mpfr_rnd_str[5] = MPFR_RND_STRINGS;
|
|||
|
||||
// number statics
|
||||
number::mode_enum number::s_mode = DEFAULT_MODE;
|
||||
int number::s_current_precision = DEFAULT_PRECISION;
|
||||
int number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS;
|
||||
string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
|
||||
|
||||
//
|
||||
|
|
|
@ -62,6 +62,11 @@ struct floating_t
|
|||
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
|
||||
operator double()
|
||||
{
|
||||
return mpfr_get_d(mpfr, s_mpfr_rnd);
|
||||
}
|
||||
|
||||
operator int()
|
||||
{
|
||||
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
|
||||
|
@ -154,7 +159,7 @@ struct number : public object
|
|||
static mode_enum s_mode;
|
||||
|
||||
// precision
|
||||
static int s_current_precision;
|
||||
static int s_decimal_digits;
|
||||
static string s_mpfr_printf_format;
|
||||
};
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ program::keyword_t program::s_keywords[] =
|
|||
|
||||
//MODE
|
||||
{ cmd_undef, "", NULL, "\nMODE"},
|
||||
{ cmd_keyword, "std", &program::std, "standard floating numbers representation. ex: [25] std" },
|
||||
{ cmd_keyword, "std", &program::std, "standard floating numbers representation. ex: std" },
|
||||
{ cmd_keyword, "fix", &program::fix, "fixed point representation. ex: 6 fix" },
|
||||
{ cmd_keyword, "sci", &program::sci, "scientific floating point representation. ex: 20 sci" },
|
||||
{ cmd_keyword, "prec", &program::precision, "get float precision in bits when first stack is not a number\n\t"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <math.h>
|
||||
|
||||
extern "C" {
|
||||
#include <readline/readline.h>
|
||||
|
@ -525,11 +526,11 @@ public:
|
|||
{
|
||||
//default float precision, float mode
|
||||
number::s_mode = DEFAULT_MODE;
|
||||
number::s_current_precision = DEFAULT_PRECISION;
|
||||
number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS;
|
||||
|
||||
// format for mpfr_printf
|
||||
stringstream ss;
|
||||
ss << number::s_current_precision;
|
||||
ss << number::s_decimal_digits;
|
||||
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD);
|
||||
|
||||
// default calc precision for MPFR
|
||||
|
|
|
@ -47,39 +47,51 @@ void help()
|
|||
case number::sci: printf("'sci'"); break;
|
||||
default: printf("unknown"); break;
|
||||
}
|
||||
printf(" with %d digits\n", number::s_current_precision);
|
||||
printf(" with %d decimal digits shown\n", number::s_decimal_digits);
|
||||
|
||||
// calc precision and rounding mode
|
||||
|
||||
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
||||
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
||||
double prec_min = (double)MPFR_PREC_MIN;
|
||||
double prec_max = (double)MPFR_PREC_MAX;
|
||||
|
||||
printf("Current floating point precision is %d bits (min=%ld bits, max=0x%lx bits)\n", (int)floating_t::s_mpfr_prec, (int64_t)prec_min, (int64_t)prec_max);
|
||||
// bits precision, decimal digits and rounding mode
|
||||
printf("Current floating point precision is %d bits\n", (int)floating_t::s_mpfr_prec);
|
||||
printf("Current rounding mode is '%s'\n", floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
int decimal_digits_from_bit_precision(int bit_precision)
|
||||
{
|
||||
return (int)ceil(bit_precision * log10(2.0));
|
||||
}
|
||||
|
||||
string make_digit_format(int decimal_digits, const char* printf_format)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << MPFR_FORMAT_BEG;
|
||||
ss << number::s_decimal_digits;
|
||||
ss << printf_format;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool check_precision_inbound(double precision)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
||||
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
||||
double prec_max = (double)MPFR_PREC_MAX;
|
||||
double prec_min = (double)MPFR_PREC_MIN;
|
||||
|
||||
if (precision < prec_min || precision > prec_max)
|
||||
ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void std()
|
||||
{
|
||||
int precision = -1;
|
||||
|
||||
if (stack_size()>=1)
|
||||
{
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
precision = int(((number*)_stack->pop_back())->_value);
|
||||
}
|
||||
|
||||
if (precision != -1)
|
||||
number::s_current_precision = precision;
|
||||
// to std mode
|
||||
number::s_mode = number::std;
|
||||
|
||||
// format for mpfr_printf
|
||||
stringstream ss;
|
||||
ss << number::s_current_precision;
|
||||
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD);
|
||||
|
||||
// calc max nb of digits user can see with the current bit precision
|
||||
number::s_decimal_digits = decimal_digits_from_bit_precision(floating_t::s_mpfr_prec);
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
}
|
||||
|
||||
void fix()
|
||||
|
@ -87,15 +99,17 @@ void fix()
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int precision = int(((number*)_stack->pop_back())->_value);
|
||||
number::s_current_precision = int(precision);
|
||||
|
||||
number::s_mode = number::fix;
|
||||
|
||||
// format for mpfr_printf
|
||||
stringstream ss;
|
||||
ss << number::s_current_precision;
|
||||
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_FIX);
|
||||
double precision = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_precision_inbound(precision))
|
||||
{
|
||||
// set mode, precision, decimal digits and print format
|
||||
number::s_mode = number::fix;
|
||||
number::s_decimal_digits = (int)precision;
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void sci()
|
||||
|
@ -103,15 +117,17 @@ void sci()
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int precision = int(((number*)_stack->pop_back())->_value);
|
||||
number::s_current_precision = int(precision);
|
||||
|
||||
number::s_mode = number::sci;
|
||||
|
||||
// format for mpfr_printf
|
||||
stringstream ss;
|
||||
ss << number::s_current_precision;
|
||||
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_SCI);
|
||||
double precision = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_precision_inbound(precision))
|
||||
{
|
||||
// set mode, precision, decimal digits and print format
|
||||
number::s_mode = number::sci;
|
||||
number::s_decimal_digits = (int)precision;
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_version()
|
||||
|
@ -173,6 +189,14 @@ void precision()
|
|||
{
|
||||
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
|
||||
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
|
||||
|
||||
// modify digits seen by user if std mode
|
||||
if (number::s_mode == number::std)
|
||||
{
|
||||
// calc max nb of digits user can see with the current bit precision
|
||||
number::s_decimal_digits = decimal_digits_from_bit_precision(floating_t::s_mpfr_prec);
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
|
|
|
@ -3,19 +3,14 @@ default erase
|
|||
|
||||
# std (1)
|
||||
erase
|
||||
1
|
||||
10 std
|
||||
-> stack should be 1
|
||||
std
|
||||
-> stack size should be 0
|
||||
-> error should be 0
|
||||
erase
|
||||
|
||||
# std (2)
|
||||
1 3 /
|
||||
-> stack should be 0.3333333333
|
||||
erase
|
||||
|
||||
# std (3)
|
||||
1 3 / 3 std
|
||||
-> stack should be 0.333
|
||||
-> stack should be 0.333333333333333333333333333333333333334
|
||||
erase
|
||||
|
||||
# fix (1)
|
||||
|
@ -29,6 +24,11 @@ erase
|
|||
-> stack should be 1.0000
|
||||
erase
|
||||
|
||||
# fix (3)
|
||||
1 fix
|
||||
-> error should be 4
|
||||
erase
|
||||
|
||||
# sci (1)
|
||||
1 12 sci
|
||||
-> stack should be 1.000000000000e+00
|
||||
|
@ -39,4 +39,9 @@ erase
|
|||
-> stack should be 1.00e+00
|
||||
erase
|
||||
|
||||
# sci (3)
|
||||
1 sci
|
||||
-> error should be 4
|
||||
erase
|
||||
|
||||
default
|
||||
|
|
Loading…
Reference in a new issue