#34: MPFR lib, general and real calc, some branch

This commit is contained in:
Louis Rubet 2017-04-18 22:53:55 +02:00
parent 4670aa77c0
commit 7ddde5dea5
7 changed files with 252 additions and 184 deletions

View file

@ -562,15 +562,8 @@ static ret_value parse(const char* entry, program& prog)
// this remaining entry is treated as an entry
if(_obj_from_string(main_entry, obj, obj_size, type, remaining_entry))
{
cout<<"parse->obj = "<<obj<<endl;
prog.push_back(obj, obj_size, type);
if (((object*)prog.back())->_type == cmd_number)
{
cout<<"((number*)prog.back())="<<(void*)prog.back()<<endl;
cout<<" (((number*)prog.back())->_value.mpfr._mpfr_d = "<<((number*)prog.back())->_value.mpfr._mpfr_d<<")"<<endl;
((number*)prog.back())->_value.mpfr._mpfr_d = (mp_limb_t*)((number*)prog.back())->_value.significand;
cout<<" -> (((number*)prog.back())->_value.mpfr._mpfr_d = "<<((number*)prog.back())->_value.mpfr._mpfr_d<<")"<<endl;
}
//TODO wtf !?
//_delete_obj_from_string(obj);
}
else

View file

@ -56,7 +56,9 @@ int rpn_start(branch& myobj)
// farg1 = first value of start command
// farg2 = last value of start command
myobj.farg2 = getf();
myobj.farg2.ensure_significand();
myobj.farg1 = getf();
myobj.farg1.ensure_significand();
return -1;
}
@ -72,7 +74,9 @@ int rpn_for(branch& myobj)
// farg2 = last value of for command
// arg1 = index of symbol to increase
myobj.farg2 = getf();
myobj.farg2.ensure_significand();
myobj.farg1 = getf();
myobj.farg1.ensure_significand();
// store symbol with first value
number num;
@ -91,6 +95,7 @@ int rpn_next(branch& myobj)
{
myobj.arg_bool = true;
myobj.farg1 = start_or_for->farg1;
myobj.farg1.ensure_significand();
}
// increment then test
@ -105,7 +110,10 @@ int rpn_next(branch& myobj)
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// check symbol variable is a number, then increase
if (_local_heap.get(string(var->_value), obj, size, type) && (type == cmd_number))
{
((number*)obj)->_value = myobj.farg1;
((number*)obj)->ensure_significand();
}
}
//test value
@ -136,6 +144,7 @@ int rpn_step(branch& myobj)
{
myobj.arg_bool = true;
myobj.farg1 = start_or_for->farg1;
myobj.farg1.ensure_significand();
}
// increment then test
@ -150,7 +159,10 @@ int rpn_step(branch& myobj)
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// check symbol variable is a number, then increase
if (_local_heap.get(string(var->_value), obj, size, type) && (type == cmd_number))
{
((number*)obj)->_value = myobj.farg1;
((number*)obj)->ensure_significand();
}
}
//test value

View file

@ -27,9 +27,11 @@ program::keyword_t program::_keywords[] =
{ cmd_keyword, "inv", &program::inv, "unarity operator inverse (1/)" },
{ cmd_keyword, "%", &program::purcent, "binary operator purcent" },
{ cmd_keyword, "%CH", &program::purcentCH, "binary operator inverse purcent" },
{ cmd_keyword, "^", &program::power, "binary operator power" },
{ cmd_keyword, "^", &program::power, "(or pow) binary operator power" },
{ cmd_keyword, "pow", &program::power, "" },
{ cmd_keyword, "sqrt", &program::squareroot, "unarity operator square root" },
{ cmd_keyword, "sq", &program::square, "unarity operator square" },
{ cmd_keyword, "sq", &program::square, "(or sqr) unarity operator square" },
{ cmd_keyword, "sqr", &program::square, "" },
{ cmd_keyword, "mod", &program::modulo, "binary operator modulo" },
//BINARY

View file

@ -77,11 +77,14 @@ void std()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number::s_default_precision = int(getf());
}
number::s_current_precision = number::s_default_precision;
number::s_mode = number::std;
cout.precision(number::s_current_precision);
cout.unsetf(ios_base::floatfield);
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = s_mpfr_printf_format_beg + ss.str() + s_mpfr_printf_format_std;
}
void fix()
@ -92,7 +95,10 @@ void fix()
number::s_current_precision = int(getf());
number::s_mode = number::fix;
cout << setprecision(number::s_current_precision) << fixed;
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = s_mpfr_printf_format_beg + ss.str() + s_mpfr_printf_format_fix;
}
void sci()
@ -103,7 +109,10 @@ void sci()
number::s_current_precision = (int)getf();
number::s_mode = number::sci;
cout << setprecision(number::s_current_precision) << scientific;
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = s_mpfr_printf_format_beg + ss.str() + s_mpfr_printf_format_sci;
}
void rpn_version()

View file

@ -2,23 +2,27 @@ void plus()
{
MIN_ARGUMENTS(2);
//TODO
//// float
//if (IS_ARG_TYPE(0, cmd_number))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_number);
// //TODO really too slow
// putf(getf() + getf());
//}
//// binary
//else if (IS_ARG_TYPE(0, cmd_binary))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_binary);
// //TODO really too slow
// putb(getb() + getb());
//}
//TODO
// float
if (IS_ARG_TYPE(0, cmd_number))
{
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_add(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}
// binary
else if (IS_ARG_TYPE(0, cmd_binary))
{
ARG_MUST_BE_OF_TYPE(1, cmd_binary);
binary* right = (binary*)_stack->back();
_stack->pop_back();
binary* left = (binary*)_stack->back();
left->_value += right->_value;
}
#if 0
// string
else if (IS_ARG_TYPE(0, cmd_string))
@ -29,177 +33,191 @@ void plus()
*((ostring*)_stack->back())->_value += second;
}
#endif
//else
// ERR_CONTEXT(ret_bad_operand_type);
else
ERR_CONTEXT(ret_bad_operand_type);
}
void minus()
{
MIN_ARGUMENTS(2);
//TODO
//// float
//if (IS_ARG_TYPE(0, cmd_number))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_number);
// //TODO really too slow
// floating_t first = getf();
// putf(getf() - first);
//}
//// binary
//else if (IS_ARG_TYPE(0, cmd_binary))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_binary);
// //TODO really too slow
// integer_t first = getb();
// putb(getb() - first);
//}
//else
// ERR_CONTEXT(ret_bad_operand_type);
// float
if (IS_ARG_TYPE(0, cmd_number))
{
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sub(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}
// binary
else if (IS_ARG_TYPE(0, cmd_binary))
{
ARG_MUST_BE_OF_TYPE(1, cmd_binary);
binary* right = (binary*)_stack->back();
_stack->pop_back();
binary* left = (binary*)_stack->back();
left->_value -= right->_value;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void mul()
{
//TODO
//// float
//if (IS_ARG_TYPE(0, cmd_number))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_number);
// //TODO really too slow
// putf(getf() * getf());
//}
//// binary
//else if (IS_ARG_TYPE(0, cmd_binary))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_binary);
// //TODO really too slow
// putb(getb() * getb());
//}
//else
// ERR_CONTEXT(ret_bad_operand_type);
// float
if (IS_ARG_TYPE(0, cmd_number))
{
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}
// binary
else if (IS_ARG_TYPE(0, cmd_binary))
{
ARG_MUST_BE_OF_TYPE(1, cmd_binary);
binary* right = (binary*)_stack->back();
_stack->pop_back();
binary* left = (binary*)_stack->back();
left->_value *= right->_value;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void div()
{
//TODO
//MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2);
//// float
//if (IS_ARG_TYPE(0, cmd_number))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_number);
// //TODO really too slow
// float
if (IS_ARG_TYPE(0, cmd_number))
{
ARG_MUST_BE_OF_TYPE(1, cmd_number);
// floating_t first = getf();
// // arithmetic faults are managed by c++
// putf(getf() / first);
//}
//// binary
//else if (IS_ARG_TYPE(0, cmd_binary))
//{
// ARG_MUST_BE_OF_TYPE(1, cmd_binary);
// if (((binary*)_stack->get_obj(0))->_value == 0)
// {
// ERR_CONTEXT(ret_div_by_zero);
// }
// else
// {
// //TODO really too slow
// integer_t first = getb();
// putb(getb() / first);
// }
//}
//else
// ERR_CONTEXT(ret_bad_operand_type);
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_div(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}
// binary
else if (IS_ARG_TYPE(0, cmd_binary))
{
ARG_MUST_BE_OF_TYPE(1, cmd_binary);
if (((binary*)_stack->get_obj(0))->_value == 0)
{
ERR_CONTEXT(ret_div_by_zero);
}
else
{
binary* right = (binary*)_stack->back();
_stack->pop_back();
binary* left = (binary*)_stack->back();
left->_value /= right->_value;
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void neg()
{
//TODO
//MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
//// float
//if (IS_ARG_TYPE(0, cmd_number))
// putf(-getf());
//// binary
//else if (IS_ARG_TYPE(0, cmd_binary))
// putb(-getb());
//else
// ERR_CONTEXT(ret_bad_operand_type);
// float
if (IS_ARG_TYPE(0, cmd_number))
{
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_neg(&left->_value.mpfr, &left->_value.mpfr, s_mpfr_rnd));
}
// binary
else if (IS_ARG_TYPE(0, cmd_binary))
((binary*)_stack->back())->_value *= -1;
else
ERR_CONTEXT(ret_bad_operand_type);
}
void inv()
{
//TODO
//MIN_ARGUMENTS(1);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
//// arithmetic faults are managed by c++
//putf(1 / getf());
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_si_div(&left->_value.mpfr, 1L, &left->_value.mpfr, s_mpfr_rnd));
}
void purcent()
{
//TODO
//MIN_ARGUMENTS(2);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
//ARG_MUST_BE_OF_TYPE(1, cmd_number);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
//putf((getf() * getf()) / 100);
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(&left->_value.mpfr, &left->_value.mpfr, 100L, s_mpfr_rnd));
}
void purcentCH()
{
//TODO
//MIN_ARGUMENTS(2);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
//ARG_MUST_BE_OF_TYPE(1, cmd_number);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
//// arithmetic faults are managed by c++
//floating_t first = getf();
//putf((100 * first) / getf());
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul_si(&right->_value.mpfr, &right->_value.mpfr, 100L, s_mpfr_rnd));
CHECK_MPFR(mpfr_div(&left->_value.mpfr, &right->_value.mpfr, &left->_value.mpfr, s_mpfr_rnd));
}
void power()
{
//TODO
//MIN_ARGUMENTS(2);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
//ARG_MUST_BE_OF_TYPE(1, cmd_number);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
//// arithmetic faults are managed by c++
//floating_t first = getf();
//putf(powl(getf(), first));
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_pow(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}
void squareroot()
{
//TODO
//MIN_ARGUMENTS(1);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
//// arithmetic faults are managed by c++
//putf(sqrtl(getf()));
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sqrt(&left->_value.mpfr, &left->_value.mpfr, s_mpfr_rnd));
}
void square()
{
//TODO
//MIN_ARGUMENTS(1);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
//floating_t first = getf();
//putf(first * first);
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sqr(&left->_value.mpfr, &left->_value.mpfr, s_mpfr_rnd));
}
void modulo()
{
//TODO
//MIN_ARGUMENTS(2);
//ARG_MUST_BE_OF_TYPE(0, cmd_number);
//ARG_MUST_BE_OF_TYPE(1, cmd_number);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
//// arithmetic faults are managed by c++
//floating_t first = getf();
//putf(fmodl(getf(), first));
number* right = (number*)_stack->back();
_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_fmod(&left->_value.mpfr, &left->_value.mpfr, &right->_value.mpfr, s_mpfr_rnd));
}

View file

@ -38,13 +38,23 @@ using namespace std;
#include "stack.h"
// default number of printed digitis
#define DEFAULT_PRECISION 12
// MPFR related constants
// 128 bits significand storing length in byters, result of mpfr_custom_get_size (128)
#define MPFR_DEF_FORMAT "%Rf"
// 128 bits significand storing length in byters, result of mpfr_custom_get_size(128)
#define MPFR_DEF_RND MPFR_RNDN
#define MPFR_128BITS_PREC 128
#define MPFR_128BITS_STORING_LENGTH 16
static string s_mpfr_printf_format_beg = "%.";
static string s_mpfr_printf_format_std = "Rg";
static string s_mpfr_printf_format_fix = "Rf";
static string s_mpfr_printf_format_sci = "Re";
static string s_mpfr_printf_format = "%.12Rg";
static mpfr_prec_t s_mpfr_prec = MPFR_128BITS_PREC;
static mpfr_rnd_t s_mpfr_rnd = MPFR_DEF_RND;
//
static int g_verbose = 0;
@ -98,19 +108,34 @@ struct floating_t
floating_t()
{
mpfr_custom_init(significand, MPFR_128BITS_STORING_LENGTH);
mpfr_custom_init_set(&mpfr, MPFR_NAN_KIND, 0, MPFR_128BITS_PREC, significand);
mpfr_custom_init_set(&mpfr, MPFR_NAN_KIND, 0, s_mpfr_prec, significand);
}
floating_t operator=(const long int val)
{
mpfr_custom_init(significand, MPFR_128BITS_STORING_LENGTH);
mpfr_custom_init_set(&mpfr, MPFR_ZERO_KIND, 0, MPFR_128BITS_PREC, significand);
mpfr_set_si(&mpfr, val, MPFR_DEF_RND);
mpfr_custom_init_set(&mpfr, MPFR_ZERO_KIND, 0, s_mpfr_prec, significand);
mpfr_set_si(&mpfr, val, s_mpfr_rnd);
}
operator int()
{
return (int)mpfr_get_si(&mpfr, MPFR_DEF_RND);
return (int)mpfr_get_si(&mpfr, s_mpfr_rnd);
}
void ensure_significand()
{
mpfr._mpfr_d = (mp_limb_t*)significand;
}
bool operator>(const floating_t right)
{
return mpfr_cmp(&mpfr, &right.mpfr) > 0;
}
bool operator<(const floating_t right)
{
return mpfr_cmp(&mpfr, &right.mpfr) < 0;
}
};
@ -155,6 +180,11 @@ struct number : public object
_value = (long)value;
}
unsigned int size() { return (unsigned int)sizeof(floating_t); }
void ensure_significand()
{
_value.mpfr._mpfr_d = (mp_limb_t*)_value.significand;
}
//
number operator=(const number& op)
@ -180,7 +210,7 @@ struct number : public object
number::mode_enum number::s_default_mode = number::std;
number::mode_enum number::s_mode = number::s_default_mode;
int number::s_default_precision = 12;
int number::s_default_precision = DEFAULT_PRECISION;
int number::s_current_precision = number::s_default_precision;
struct binary : public object
@ -333,6 +363,7 @@ struct branch : public object
branch_fn_t _fn;
// args used by cmd_branch cmds
int arg1, arg2, arg3;
//TODO change to int
floating_t farg1, farg2;
bool arg_bool;
unsigned int _len;
@ -344,36 +375,31 @@ void object::show(ostream& stream)
switch(_type)
{
case cmd_number:
//TODO
//stream << ((number*)this)->_value;
stream<<"number._value.mpfr="<<&((number*)this)->_value.mpfr<<endl;
stream<<"number._value.mpfr._mpfr_d="<<(void*)((number*)this)->_value.mpfr._mpfr_d<<endl;
stream<<"number._value.significand="<<(void*)((number*)this)->_value.significand<<endl;
(void)mpfr_printf(MPFR_DEF_FORMAT, &((number*)this)->_value.mpfr);
((number*)this)->ensure_significand();
(void)mpfr_printf(s_mpfr_printf_format.c_str(), &((number*)this)->_value.mpfr);
break;
case cmd_binary:
{
//TODO
//cout << "# ";
//switch(((binary*)this)->s_mode)
//{
// case binary::dec: stream<<std::right<<std::setw(8)<<std::dec<<((binary*)this)->_value<<" d"; break;
// case binary::hex: stream<<std::right<<std::setw(8)<<std::hex<<((binary*)this)->_value<<" h"; break;
// case binary::oct: stream<<std::right<<std::setw(8)<<std::oct<<((binary*)this)->_value<<" o"; break;
// case binary::bin:
// {
// string mybin;
// for (int i = (int)(log((floating_t)((binary*)this)->_value) / log(2.)); i>=0; i--)
// {
// if (((binary*)this)->_value & (1 << i))
// mybin+='1';
// else
// mybin+='0';
// }
// stream<<std::right<<std::setw(20)<<std::oct<<mybin<<" b";
// }
// break;
//}
cout << "# ";
switch(((binary*)this)->s_mode)
{
case binary::dec: stream<<std::right<<std::setw(8)<<std::dec<<((binary*)this)->_value<<" d"; break;
case binary::hex: stream<<std::right<<std::setw(8)<<std::hex<<((binary*)this)->_value<<" h"; break;
case binary::oct: stream<<std::right<<std::setw(8)<<std::oct<<((binary*)this)->_value<<" o"; break;
case binary::bin:
{
string mybin;
for (int i = (int)(log((double)((binary*)this)->_value) / log(2.)); i>=0; i--)
{
if (((binary*)this)->_value & (1 << i))
mybin+='1';
else
mybin+='0';
}
stream<<std::right<<std::setw(20)<<std::oct<<mybin<<" b";
}
break;
}
}
break;
case cmd_string:
@ -500,6 +526,14 @@ public:
else
{
stk.push_back(seq_obj(i), seq_len(i), type);
// numbers: ensure that significand is correctly recorded by object
if (type == cmd_number)
{
number* k = (number*)stk.back();
k->ensure_significand();
}
i++;
}
}
@ -796,6 +830,8 @@ private:
#define ARG_MUST_BE_OF_TYPE(num, type) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } } while(0)
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } } while(0)
#define IS_ARG_TYPE(num, type) (_stack->get_type(num) == (type))
//TODO
#define CHECK_MPFR(op) do { (void)(op); } while(0)
// keywords implementation
#include "rpn-general.h"
@ -820,7 +856,6 @@ private:
static void apply_default(void)
{
//default precision
cout << setprecision(number::s_default_precision);
number::s_mode = number::s_default_mode;
//default binary mode

View file

@ -44,7 +44,6 @@ public:
_base = (char*)realloc(_base, _total_size);
}
cout<<"current = "<<(void*)_current<<", index is "<<_count<<endl;
if (!dont_copy)
memcpy(_current, obj, size);
_vlen.push_back(size);