#210: google-styled code

This commit is contained in:
Louis Rubet 2018-08-12 11:50:49 +02:00
parent 51c49c1aed
commit abe2bd12e8
23 changed files with 4729 additions and 5184 deletions

1
src/.clang-format Normal file
View file

@ -0,0 +1 @@
BasedOnStyle: Google

View file

@ -22,7 +22,8 @@
// 128 bits significand precision // 128 bits significand precision
#define MPFR_DEFAULT_PREC_BITS 128 #define MPFR_DEFAULT_PREC_BITS 128
// 128 bits significand storing length in bytes, result of mpfr_custom_get_size(128) // 128 bits significand storing length in bytes, result of
// mpfr_custom_get_size(128)
#define MPFR_DEFAULT_STORING_LENGTH_BYTES 16 #define MPFR_DEFAULT_STORING_LENGTH_BYTES 16
// constants // constants
@ -42,37 +43,46 @@
#define MPFR_FORMAT_SCI "Re" #define MPFR_FORMAT_SCI "Re"
#define MPFR_FORMAT_HEX "%Ra" #define MPFR_FORMAT_HEX "%Ra"
#define MPFR_RND_STRINGS { "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" } #define MPFR_RND_STRINGS \
{ "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
// return values, used by all classes // return values, used by all classes
// //
typedef enum { typedef enum {
ret_ok, ret_ok,
ret_unknown_err, ret_unknown_err,
ret_missing_operand, ret_missing_operand,
ret_bad_operand_type, ret_bad_operand_type,
ret_out_of_range, ret_out_of_range,
ret_unknown_variable, ret_unknown_variable,
ret_internal, ret_internal,
ret_deadly, ret_deadly,
ret_good_bye, ret_good_bye,
ret_not_impl, ret_not_impl,
ret_nop, ret_nop,
ret_syntax, ret_syntax,
ret_div_by_zero, ret_div_by_zero,
ret_runtime_error, ret_runtime_error,
ret_abort_current_entry, ret_abort_current_entry,
ret_max ret_max
} ret_value; } ret_value;
#define RET_VALUE_STRINGS { \ #define RET_VALUE_STRINGS \
"ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", \ { \
"deadly", "goodbye", "not implemented", "no operation", "syntax error", "division by zero", "runtime error", "aborted current entry" \ "ok", "unknown command", "missing operand", "bad operand type", \
} "out of range", "unknown variable", "internal error, aborting", \
"deadly", "goodbye", "not implemented", "no operation", \
"syntax error", "division by zero", "runtime error", \
"aborted current entry" \
}
// command types // command types
// //
#define CMD_TYPE_STRINGS { "undef", "number", "complex", "string", "symbol", "program", "keyword", "keyword" } #define CMD_TYPE_STRINGS \
{ \
"undef", "number", "complex", "string", "symbol", "program", "keyword", \
"keyword" \
}
// history // history
#define HISTORY_FILE ".rpn_history" #define HISTORY_FILE ".rpn_history"
@ -99,14 +109,14 @@ typedef enum {
#error "Invalid MPFR Exp format" #error "Invalid MPFR Exp format"
#endif #endif
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(h,i) ((h) > (i) ? (h) : (i)) #define MAX(h, i) ((h) > (i) ? (h) : (i))
#define MPFR_EXP_INF (MPFR_EXP_MIN+3) #define MPFR_EXP_INF (MPFR_EXP_MIN + 3)
#define MPFR_EXP_NAN (MPFR_EXP_MIN+2) #define MPFR_EXP_NAN (MPFR_EXP_MIN + 2)
#define MPFR_EXP(x) ((x)->_mpfr_exp) #define MPFR_EXP(x) ((x)->_mpfr_exp)
#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF) #define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF)
#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x),0)) #define MPFR_UNLIKELY(x) (__builtin_expect(!!(x), 0))
#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN) #define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN)
#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF) #define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF)
#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0) #define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0)

View file

@ -2,97 +2,92 @@
#define DEBUG_H #define DEBUG_H
static void dump8(unsigned char* to_dump, unsigned long offset, static void dump8(unsigned char* to_dump, unsigned long offset,
unsigned long size) unsigned long size) {
{ const int block_size = 1;
const int block_size = 1; const int block_per_line = 16;
const int block_per_line = 16; int max_line = size / block_size;
int max_line = size / block_size; unsigned char mychar;
unsigned char mychar; int i;
int i; int j;
int j; for (i = 0; i < max_line; i++) {
for (i = 0; i < max_line; i++) if ((i % block_per_line) == 0) {
{ if (i > 0) {
if ((i % block_per_line) == 0)
{
if (i > 0)
{
printf(" ");
for (j = i - block_per_line; j < i; j++)
{
mychar = *(to_dump + j);
if ((mychar < 32) || (mychar >= 127))
mychar = '.';
printf("%c", mychar);
}
}
printf("\n%08lX:", offset + i * block_size);
}
printf(" %02hhX", *(to_dump + i));
}
if (i > 0)
{
printf(" "); printf(" ");
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++) for (j = i - block_per_line; j < i; j++) {
{ mychar = *(to_dump + j);
mychar = *(to_dump + j); if ((mychar < 32) || (mychar >= 127)) mychar = '.';
if ((mychar < 32) || (mychar >= 127)) printf("%c", mychar);
mychar = '.';
printf("%c", mychar);
} }
}
printf("\n%08lX:", offset + i * block_size);
} }
printf("\n"); printf(" %02hhX", *(to_dump + i));
}
if (i > 0) {
printf(" ");
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++) {
mychar = *(to_dump + j);
if ((mychar < 32) || (mychar >= 127)) mychar = '.';
printf("%c", mychar);
}
}
printf("\n");
} }
// //
#define TRACE(...) do { printf(__VA_ARGS__); } while(0) #define TRACE(...) \
do { \
printf(__VA_ARGS__); \
} while (0)
// chrono // chrono
#include <time.h> #include <time.h>
static int chrono_next = 0; static int chrono_next = 0;
static struct static struct {
{ struct timespec ts_point;
struct timespec ts_point; char comment[256];
char comment[256];
} chrono_point[24]; } chrono_point[24];
static void chrono_start() static void chrono_start() {
{ clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point); strcpy(chrono_point[0].comment, "START");
strcpy(chrono_point[0].comment, "START"); chrono_next = 1;
chrono_next = 1;
} }
static void chrono_add(const char* comment) static void chrono_add(const char* comment) {
{ clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point); strcpy(chrono_point[chrono_next].comment, comment);
strcpy(chrono_point[chrono_next].comment, comment); chrono_next++;
chrono_next++;
} }
static uint64_t chrono_diff_us(struct timespec* ts_from, struct timespec* ts_to) static uint64_t chrono_diff_us(struct timespec* ts_from,
{ struct timespec* ts_to) {
uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL + ((uint64_t)ts_from->tv_nsec) / 1000UL; uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL +
uint64_t to = (uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL; ((uint64_t)ts_from->tv_nsec) / 1000UL;
return to - from; uint64_t to =
(uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
return to - from;
} }
static void chrono_all_print(void) static void chrono_all_print(void) {
{ for (int i = 1; i < chrono_next; i++) {
for(int i = 1; i < chrono_next; i++) printf("CHRONO [%lu us] %s\n",
{ chrono_diff_us(&chrono_point[i - 1].ts_point,
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[i-1].ts_point, &chrono_point[i].ts_point), chrono_point[i].comment); &chrono_point[i].ts_point),
} chrono_point[i].comment);
}
} }
static void chrono_print(int chrono) static void chrono_print(int chrono) {
{ if (chrono >= 1) {
if (chrono >= 1) printf("CHRONO [%lu us] %s\n",
{ chrono_diff_us(&chrono_point[chrono - 1].ts_point,
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[chrono-1].ts_point, &chrono_point[chrono].ts_point), chrono_point[chrono].comment); &chrono_point[chrono].ts_point),
} chrono_point[chrono].comment);
}
} }
#define max(a, b) (((a)>(b))?(a):(b)) #define max(a, b) (((a) > (b)) ? (a) : (b))
#endif #endif

View file

@ -1,12 +1,12 @@
// std c // std c
#include <signal.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
// internal includes // internal includes
#include "program.hpp" #include "program.hpp"
@ -16,149 +16,137 @@ static stack s_global_stack;
static program* s_prog_to_interrupt = NULL; static program* s_prog_to_interrupt = NULL;
// actions to be done at rpn exit // actions to be done at rpn exit
void exit_interactive_rpn() void exit_interactive_rpn() {
{ struct passwd* pw = getpwuid(getuid());
struct passwd* pw = getpwuid(getuid()); if (pw != NULL) {
if (pw != NULL) char history_path[PATH_MAX];
{ sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
// trunc current history // trunc current history
ofstream history(history_path, ios_base::out|ios_base::trunc); ofstream history(history_path, ios_base::out | ios_base::trunc);
history.close(); history.close();
// save it // save it
if (linenoiseHistorySave(history_path) != 0) if (linenoiseHistorySave(history_path) != 0)
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno)); fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n",
} history_path, errno, strerror(errno));
}
} }
// actions to be done at rpn exit // actions to be done at rpn exit
void init_interactive_rpn() void init_interactive_rpn() {
{ struct passwd* pw = getpwuid(getuid());
struct passwd* pw = getpwuid(getuid()); if (pw != NULL) {
if (pw != NULL) char history_path[PATH_MAX];
{ sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
// don't care about errors // don't care about errors
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES); linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
linenoiseHistoryLoad(history_path); linenoiseHistoryLoad(history_path);
} }
} }
// handle CtrlC signal // handle CtrlC signal
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
{ if (s_prog_to_interrupt != NULL) {
if (s_prog_to_interrupt != NULL) s_prog_to_interrupt->stop();
{ s_prog_to_interrupt = NULL;
s_prog_to_interrupt->stop(); }
s_prog_to_interrupt = NULL;
}
exit_interactive_rpn(); exit_interactive_rpn();
} }
// handle SIGSEGV signal // handle SIGSEGV signal
static void segv_handler(int sig, siginfo_t* siginfo, void* context) static void segv_handler(int sig, siginfo_t* siginfo, void* context) {
{ fprintf(stderr, "Internal error\n");
fprintf(stderr, "Internal error\n"); s_prog_to_interrupt->stop();
s_prog_to_interrupt->stop(); s_prog_to_interrupt = NULL;
s_prog_to_interrupt = NULL;
} }
static void catch_signals(program* prog) static void catch_signals(program* prog) {
{ struct sigaction act;
struct sigaction act;
s_prog_to_interrupt = prog; s_prog_to_interrupt = prog;
act.sa_sigaction = &ctrlc_handler; act.sa_sigaction = &ctrlc_handler;
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, NULL) < 0) if (sigaction(SIGINT, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']", errno, strerror(errno)); (void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']",
errno, strerror(errno));
act.sa_sigaction = &segv_handler; act.sa_sigaction = &segv_handler;
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0) if (sigaction(SIGSEGV, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno)); (void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']",
errno, strerror(errno));
} }
// //
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{ int ret = 0;
int ret = 0; bool go_on = true;
bool go_on = true;
// apply default configuration // apply default configuration
program::apply_default(); program::apply_default();
// run with interactive prompt // run with interactive prompt
if (argc == 1) if (argc == 1) {
{ // init history
// init history init_interactive_rpn();
init_interactive_rpn();
// entry loop // entry loop
while(go_on) while (go_on) {
{ // make program from interactive entry
// make program from interactive entry program prog;
program prog; switch (program::entry(prog)) {
switch (program::entry(prog)) case ret_good_bye:
{ go_on = false;
case ret_good_bye: break;
go_on = false; case ret_abort_current_entry:
break; break;
case ret_abort_current_entry: default:
break; // user could stop prog with CtrlC
default: catch_signals(&prog);
// user could stop prog with CtrlC
catch_signals(&prog);
// run it // run it
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye) if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
go_on = false; go_on = false;
else else
program::show_stack(s_global_stack); program::show_stack(s_global_stack);
break; break;
} }
}
// manage history and exit
exit_interactive_rpn();
}
// run with cmd line arguments
else
{
program prog;
string entry;
int i;
// make one string from entry
for (i=1; i<argc; i++)
{
entry += argv[i];
entry += ' ';
}
// make program
ret = program::parse(entry.c_str(), prog);
if (ret == ret_ok)
{
string separator = "";
// user could stop prog with CtrlC
catch_signals(&prog);
// run it
ret = prog.run(s_global_stack, s_global_heap);
program::show_stack(s_global_stack, true);
}
} }
mpfr_free_cache(); // manage history and exit
exit_interactive_rpn();
}
// run with cmd line arguments
else {
program prog;
string entry;
int i;
return ret; // make one string from entry
for (i = 1; i < argc; i++) {
entry += argv[i];
entry += ' ';
}
// make program
ret = program::parse(entry.c_str(), prog);
if (ret == ret_ok) {
string separator = "";
// user could stop prog with CtrlC
catch_signals(&prog);
// run it
ret = prog.run(s_global_stack, s_global_heap);
program::show_stack(s_global_stack, true);
}
}
mpfr_free_cache();
return ret;
} }

View file

@ -1,9 +1,9 @@
#include <string>
#include <math.h> #include <math.h>
#include <string>
using namespace std; using namespace std;
#include "mpfr.h"
#include "constant.h" #include "constant.h"
#include "mpfr.h"
#include "object.hpp" #include "object.hpp"
// floating_t statics // floating_t statics
@ -20,233 +20,198 @@ string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
// //
const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS; const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
static bool is_min(mpfr_t p, mpfr_prec_t prec) static bool is_min(mpfr_t p, mpfr_prec_t prec) {
{ // see mpfr_vasprintf code
// see mpfr_vasprintf code bool ret;
bool ret; int round_away;
int round_away; switch (floating_t::s_mpfr_rnd) {
switch (floating_t::s_mpfr_rnd) case MPFR_RNDA:
{ round_away = 1;
case MPFR_RNDA: break;
round_away = 1; case MPFR_RNDD:
break; round_away = MPFR_IS_NEG(p);
case MPFR_RNDD: break;
round_away = MPFR_IS_NEG (p); case MPFR_RNDU:
break; round_away = MPFR_IS_POS(p);
case MPFR_RNDU: break;
round_away = MPFR_IS_POS (p); case MPFR_RNDN: {
break; /* compare |p| to y = 0.5*10^(-prec) */
case MPFR_RNDN: mpfr_t y;
{ mpfr_exp_t e = MAX(MPFR_PREC(p), 56);
/* compare |p| to y = 0.5*10^(-prec) */ mpfr_init2(y, e + 8);
mpfr_t y; do {
mpfr_exp_t e = MAX (MPFR_PREC (p), 56); /* find a lower approximation of
mpfr_init2 (y, e + 8); 0.5*10^(-prec) different from |p| */
do e += 8;
{ mpfr_set_prec(y, e);
/* find a lower approximation of mpfr_set_si(y, -prec, MPFR_RNDN);
0.5*10^(-prec) different from |p| */ mpfr_exp10(y, y, MPFR_RNDD);
e += 8; mpfr_div_2ui(y, y, 1, MPFR_RNDN);
mpfr_set_prec (y, e); } while (mpfr_cmpabs(y, p) == 0);
mpfr_set_si (y, -prec, MPFR_RNDN);
mpfr_exp10 (y, y, MPFR_RNDD);
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
} while (mpfr_cmpabs (y, p) == 0);
round_away = mpfr_cmpabs (y, p) < 0; round_away = mpfr_cmpabs(y, p) < 0;
mpfr_clear (y); mpfr_clear(y);
} } break;
break; default:
default: round_away = 0;
round_away = 0; }
}
if (round_away) if (round_away) /* round away from zero: the last output digit is '1' */
/* round away from zero: the last output digit is '1' */ ret = true;
ret = true; else
else /* only zeros in fractional part */
/* only zeros in fractional part */ ret = false;
ret = false; return ret;
return ret;
} }
static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL) static void print_fix(FILE* stream, mpfr_t real, int base,
{ const char* write_after_sign = NULL) {
// see mpfr_vasprintf code // see mpfr_vasprintf code
mpfr_exp_t exp = mpfr_get_exp(real); mpfr_exp_t exp = mpfr_get_exp(real);
int digits = 0; //forced 0 digits after separator int digits = 0; // forced 0 digits after separator
int i; int i;
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) {
{ if (MPFR_IS_NAN(real))
if (MPFR_IS_NAN(real)) fputs("nan", stream);
fputs("nan", stream); else if (MPFR_IS_INF(real)) {
else if (MPFR_IS_INF(real)) if (MPFR_IS_NEG(real)) fputc('-', stream);
{ fputs("inf", stream);
if (MPFR_IS_NEG(real)) } else {
fputc('-', stream); // zero
fputs("inf", stream); if (MPFR_IS_NEG(real)) fputc('-', stream); // signed zero is allowed
} if (write_after_sign != NULL) fputs(write_after_sign, stream);
else fputc('0', stream);
{ if (digits > 0) {
// zero fputc('.', stream);
if (MPFR_IS_NEG(real)) for (i = 0; i < digits; i++) fputc('0', stream);
fputc('-', stream);//signed zero is allowed }
if (write_after_sign != NULL)
fputs(write_after_sign, stream);
fputc('0', stream);
if (digits > 0)
{
fputc('.', stream);
for(i = 0; i < digits; i++)
fputc('0', stream);
}
}
} }
else if (exp < -digits) } else if (exp < -digits) {
{ if (MPFR_IS_NEG(real)) fputc('-', stream);
if (MPFR_IS_NEG(real)) if (write_after_sign != NULL) fputs(write_after_sign, stream);
fputc('-', stream); fputc('0', stream);
if (write_after_sign != NULL) if (digits > 0) {
fputs(write_after_sign, stream); fputc('.', stream);
for (i = 0; i < digits - 1; i++) fputc('0', stream);
if (is_min(real, digits))
fputc('1', stream);
else
fputc('0', stream); fputc('0', stream);
if (digits > 0) }
{ } else {
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real,
floating_t::s_mpfr_rnd);
char* print_from;
if (str != NULL) {
int len = strlen(str);
print_from = str;
if (len > 0) {
if (print_from[0] == '-') {
fputc(print_from[0], stream);
len--;
print_from++;
} else if (print_from[0] == '+') {
len--;
print_from++;
}
if (write_after_sign != NULL) fputs(write_after_sign, stream);
if (exp < 0) {
fputc('0', stream);
if (digits > 0) {
fputc('.', stream);
for (i = 0; i < -(int)exp; i++) fputc('0', stream);
fputs(str, stream);
for (i = 0; i < (int)(digits - len + exp); i++) fputc('0', stream);
}
} else {
if (exp == 0)
fputc('0', stream);
else
for (i = 0; i < (int)exp; i++) fputc(print_from[i], stream);
if (digits > 0) {
fputc('.', stream); fputc('.', stream);
for (i = 0; i< digits - 1; i++)
fputc('0', stream);
if (is_min(real, digits)) int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
fputc('1', stream); for (i = (int)exp; i < remaining + (int)exp; i++)
else fputc(print_from[i], stream);
fputc('0', stream); for (i = 0; i < (int)(exp + digits - len); i++) fputc('0', stream);
} }
}
else
{
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, floating_t::s_mpfr_rnd);
char* print_from;
if(str != NULL)
{
int len = strlen(str);
print_from = str;
if (len > 0)
{
if (print_from[0] == '-')
{
fputc(print_from[0], stream);
len--;
print_from++;
}
else if (print_from[0] == '+')
{
len--;
print_from++;
}
if (write_after_sign != NULL)
fputs(write_after_sign, stream);
if (exp < 0)
{
fputc('0', stream);
if (digits > 0)
{
fputc('.', stream);
for (i = 0; i < -(int)exp; i++)
fputc('0', stream);
fputs(str, stream);
for (i = 0; i < (int)(digits - len + exp); i++)
fputc('0', stream);
}
}
else
{
if (exp == 0)
fputc('0', stream);
else
for (i = 0; i < (int)exp; i++)
fputc(print_from[i], stream);
if (digits > 0)
{
fputc('.', stream);
int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
for (i = (int)exp; i < remaining + (int)exp; i++)
fputc(print_from[i], stream);
for (i = 0; i < (int)(exp + digits - len); i++)
fputc('0', stream);
}
}
}
mpfr_free_str(str);
} }
}
mpfr_free_str(str);
} }
}
} }
void object::show(FILE* stream) void object::show(FILE* stream) {
{ int digits;
int digits; char* str;
char* str; char base[32];
char base[32];
switch(_type) switch (_type) {
{
case cmd_number: case cmd_number:
switch(((number*)this)->_representation) switch (((number*)this)->_representation) {
{ case number::dec:
case number::dec: mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr); ((number*)this)->_value.mpfr);
break; break;
case number::hex: case number::hex:
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x"); print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
break; break;
case number::bin: case number::bin:
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b"); print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
break; break;
case number::base: case number::base:
sprintf(base, "%db", ((number*)this)->_base); sprintf(base, "%db", ((number*)this)->_base);
print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base, base); print_fix(stream, ((number*)this)->_value.mpfr,
break; ((number*)this)->_base, base);
default: break;
fprintf(stream, "<unknown number representation>"); default:
break; fprintf(stream, "<unknown number representation>");
} break;
break; }
break;
case cmd_complex: case cmd_complex:
switch(((complex*)this)->_representation) switch (((complex*)this)->_representation) {
{ case number::dec:
case number::dec: fprintf(stream, "(");
fprintf(stream, "("); mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr); ((complex*)this)->re()->mpfr);
fprintf(stream, ","); fprintf(stream, ",");
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->im()->mpfr); mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
fprintf(stream, ")"); ((complex*)this)->im()->mpfr);
break; fprintf(stream, ")");
case number::hex: break;
fprintf(stream, "("); case number::hex:
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->re()->mpfr); fprintf(stream, "(");
fprintf(stream, ","); mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->im()->mpfr); ((complex*)this)->re()->mpfr);
fprintf(stream, ")"); fprintf(stream, ",");
break; mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
default: ((complex*)this)->im()->mpfr);
fprintf(stream, "<unknown complex representation>"); fprintf(stream, ")");
} break;
break; default:
fprintf(stream, "<unknown complex representation>");
}
break;
case cmd_string: case cmd_string:
fprintf(stream, "\"%s\"", ((ostring*)this)->_value); fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
break; break;
case cmd_program: case cmd_program:
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value); fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
break; break;
case cmd_symbol: case cmd_symbol:
fprintf(stream, "'%s'", ((symbol*)this)->_value); fprintf(stream, "'%s'", ((symbol*)this)->_value);
break; break;
case cmd_keyword: case cmd_keyword:
case cmd_branch: case cmd_branch:
fprintf(stream, "%s", ((keyword*)this)->_value); fprintf(stream, "%s", ((keyword*)this)->_value);
break; break;
default: default:
fprintf(stream, "< unknown object representation >"); fprintf(stream, "< unknown object representation >");
break; break;
} }
} }

View file

@ -7,15 +7,15 @@
// definitions for objects // definitions for objects
//// ////
typedef enum { typedef enum {
cmd_undef, cmd_undef,
cmd_number,// floating point number cmd_number, // floating point number
cmd_complex,// complex, couple of floating point numbers cmd_complex, // complex, couple of floating point numbers
cmd_string,// string like "string" cmd_string, // string like "string"
cmd_symbol,// symbol like 'symbol' cmd_symbol, // symbol like 'symbol'
cmd_program,// program like << instructions >> cmd_program, // program like << instructions >>
cmd_keyword,// langage keyword cmd_keyword, // langage keyword
cmd_branch,// langage branch keyword cmd_branch, // langage branch keyword
cmd_max cmd_max
} cmd_type_t; } cmd_type_t;
class program; class program;
@ -26,330 +26,262 @@ typedef int (program::*branch_fn_t)(branch&);
// MPFR object // MPFR object
//// ////
struct floating_t struct floating_t {
{ mpfr_prec_t mpfr_prec; // precision in bits
mpfr_prec_t mpfr_prec;// precision in bits unsigned int mpfr_prec_bytes; // significand storing length in bytes
unsigned int mpfr_prec_bytes;// significand storing length in bytes mpfr_t mpfr; // mpfr object
mpfr_t mpfr;//mpfr object
void init() void init() {
{ void* significand = (void*)(this + 1);
void* significand = (void*)(this+1); mpfr_prec = s_mpfr_prec;
mpfr_prec = s_mpfr_prec; mpfr_prec_bytes = s_mpfr_prec_bytes;
mpfr_prec_bytes = s_mpfr_prec_bytes; mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS); mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand); }
}
void move() void move() {
{ void* significand = (void*)(this + 1);
void* significand = (void*)(this+1); mpfr_custom_move(mpfr, significand);
mpfr_custom_move(mpfr, significand); }
}
floating_t& operator=(const double val) floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); }
{
mpfr_set_d(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const long int val) floating_t& operator=(const long int val) {
{ mpfr_set_si(mpfr, val, s_mpfr_rnd);
mpfr_set_si(mpfr, val, s_mpfr_rnd); }
}
floating_t& operator=(const unsigned long val) floating_t& operator=(const unsigned long val) {
{ mpfr_set_ui(mpfr, val, s_mpfr_rnd);
mpfr_set_ui(mpfr, val, s_mpfr_rnd); }
}
operator double() operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); }
{
return mpfr_get_d(mpfr, s_mpfr_rnd);
}
operator int() operator int() { return (int)mpfr_get_si(mpfr, s_mpfr_rnd); }
{
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
}
operator long()
{
return mpfr_get_si(mpfr, s_mpfr_rnd);
}
bool operator>(const floating_t right) operator long() { return mpfr_get_si(mpfr, s_mpfr_rnd); }
{
return mpfr_cmp(mpfr, right.mpfr) > 0;
}
bool operator<(const floating_t right) bool operator>(const floating_t right) {
{ return mpfr_cmp(mpfr, right.mpfr) > 0;
return mpfr_cmp(mpfr, right.mpfr) < 0; }
}
// default precision in bits, precision length in bytes, rounding mode bool operator<(const floating_t right) {
static mpfr_prec_t s_mpfr_prec; return mpfr_cmp(mpfr, right.mpfr) < 0;
static unsigned int s_mpfr_prec_bytes; }
static mpfr_rnd_t s_mpfr_rnd;
static const char* s_mpfr_rnd_str[5]; // default precision in bits, precision length in bytes, rounding mode
static mpfr_prec_t s_mpfr_prec;
static unsigned int s_mpfr_prec_bytes;
static mpfr_rnd_t s_mpfr_rnd;
static const char* s_mpfr_rnd_str[5];
}; };
// object - a generic stack object // object - a generic stack object
//// ////
struct object struct object {
{ // object type
// object type cmd_type_t _type;
cmd_type_t _type; unsigned int _size;
unsigned int _size;
// //
unsigned int size() { return _size; } unsigned int size() { return _size; }
void show(FILE* stream = stdout); void show(FILE* stream = stdout);
// //
static const char* s_cmd_type_string[cmd_max]; static const char* s_cmd_type_string[cmd_max];
}; };
// stack objects derived from object // stack objects derived from object
//// ////
struct number : public object struct number : public object {
{ // members
// members enum { dec, hex, bin, base } _representation;
enum { // base
dec, // carefull: _base is used only if _representation = base
hex, int _base;
bin, // mind that float value is at the end of the object
base // because its mantissa is just after the obj in memory
} _representation; floating_t _value;
// 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;
// publics // publics
number() { _type = cmd_number; } number() { _type = cmd_number; }
void init() void init() {
{ _type = cmd_number;
_type = cmd_number; _representation = dec;
_representation = dec; _value.init();
_value.init(); }
}
void move() void move() { _value.move(); }
{
_value.move();
}
void set(unsigned long value) void set(unsigned long value) {
{ _type = cmd_number;
_type = cmd_number; _value = value;
_value = value; }
}
static unsigned int calc_size() static unsigned int calc_size() {
{ return (unsigned int)(sizeof(number) + floating_t::s_mpfr_prec_bytes);
return (unsigned int)(sizeof(number)+floating_t::s_mpfr_prec_bytes); }
}
// representation mode // representation mode
typedef enum { typedef enum { std, fix, sci } mode_enum;
std, static mode_enum s_mode;
fix,
sci
} mode_enum;
static mode_enum s_mode;
// precision // precision
static int s_decimal_digits; static int s_decimal_digits;
static string s_mpfr_printf_format; static string s_mpfr_printf_format;
}; };
// stack objects derived from object // stack objects derived from object
//// ////
struct complex : public object struct complex : public object {
{ enum { dec, hex } _representation;
enum { // mind that re float value is at the end of the object
dec, // because its mantissa is just after the obj in memory
hex floating_t _re;
} _representation;
// mind that re float value is at the end of the object
// because its mantissa is just after the obj in memory
floating_t _re;
complex() { _type = cmd_complex; } complex() { _type = cmd_complex; }
// re and im float values are at the end of the object // re and im float values are at the end of the object
floating_t* re() { return &_re; } floating_t* re() { return &_re; }
floating_t* im() { return (floating_t*)((char*)&_re + sizeof(floating_t) + _re.mpfr_prec_bytes); } floating_t* im() {
return (floating_t*)((char*)&_re + sizeof(floating_t) +
_re.mpfr_prec_bytes);
}
void init() void init() {
{ _type = cmd_complex;
_type = cmd_complex; _representation = dec;
_representation = dec; re()->init();
re()->init(); im()->init();
im()->init(); }
}
void move() void move() {
{ re()->move();
re()->move(); im()->move();
im()->move(); }
}
static unsigned int calc_size() static unsigned int calc_size() {
{ return (
return (unsigned int)(sizeof(complex)+2*(sizeof(floating_t)+floating_t::s_mpfr_prec_bytes)); unsigned int)(sizeof(complex) +
} 2 * (sizeof(floating_t) + floating_t::s_mpfr_prec_bytes));
}
}; };
struct ostring : public object struct ostring : public object {
{ // ostring may first have been allocated with len+1 bytes
// ostring may first have been allocated with len+1 bytes void set(const char* value, unsigned int len) {
void set(const char* value, unsigned int len) _type = cmd_string;
{ if (value != NULL) {
_type = cmd_string; if (len > 0) (void)memcpy(_value, value, len);
if (value != NULL) _value[len] = 0;
{ _len = len;
if (len>0) } else {
(void)memcpy(_value, value, len); _value[_len] = 0;
_value[len] = 0; _len = 0;
_len = len;
}
else
{
_value[_len] = 0;
_len = 0;
}
} }
}
// length of _value, not including the terminal '\0' // length of _value, not including the terminal '\0'
unsigned int _len; unsigned int _len;
char _value[0]; char _value[0];
}; };
struct oprogram : public object struct oprogram : public object {
{ // oprogram may first have been allocated with len+1 bytes
// oprogram may first have been allocated with len+1 bytes void set(const char* value, unsigned int len) {
void set(const char* value, unsigned int len) _type = cmd_program;
{ if (value != NULL) {
_type = cmd_program; if (len > 0) (void)memcpy(_value, value, len);
if (value != NULL) _value[len] = 0;
{ _len = len;
if (len>0) } else {
(void)memcpy(_value, value, len); _value[0] = 0;
_value[len] = 0; _len = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
} }
}
// length of _value, not includiong the terminal '\0' // length of _value, not includiong the terminal '\0'
unsigned int _len; unsigned int _len;
char _value[0]; char _value[0];
}; };
struct symbol : public object struct symbol : public object {
{ // symbol may first have been allocated with len+1 bytes
// symbol may first have been allocated with len+1 bytes void set(const char* value, unsigned int len, bool auto_eval) {
void set(const char* value, unsigned int len, bool auto_eval) _type = cmd_symbol;
{ _auto_eval = auto_eval;
_type = cmd_symbol;
_auto_eval = auto_eval;
if (value != NULL) if (value != NULL) {
{ if (len > 0) (void)memcpy(_value, value, len);
if (len>0) _value[len] = 0;
(void)memcpy(_value, value, len); _len = len;
_value[len] = 0; } else {
_len = len; _value[0] = 0;
} _len = 0;
else
{
_value[0] = 0;
_len = 0;
}
} }
}
// //
bool _auto_eval; bool _auto_eval;
// length of _value, not includiong the terminal '\0' // length of _value, not includiong the terminal '\0'
unsigned int _len; unsigned int _len;
char _value[0]; char _value[0];
}; };
struct keyword : public object struct keyword : public object {
{ // keyword may first have been allocated with len+1 bytes
// keyword may first have been allocated with len+1 bytes void set(program_fn_t fn, const char* value, unsigned int len) {
void set(program_fn_t fn, const char* value, unsigned int len) _type = cmd_keyword;
{ _fn = fn;
_type = cmd_keyword; if (value != NULL) {
_fn = fn; if (len > 0) (void)memcpy(_value, value, len);
if (value != NULL) _value[len] = 0;
{ _len = len;
if (len>0) } else {
(void)memcpy(_value, value, len); _value[0] = 0;
_value[len] = 0; _len = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
} }
}
// //
program_fn_t _fn; program_fn_t _fn;
// length of _value, not includiong the terminal '\0' // length of _value, not includiong the terminal '\0'
unsigned int _len; unsigned int _len;
char _value[0]; char _value[0];
}; };
struct branch : public object struct branch : public object {
{ //
// void set(branch_fn_t fn, const char* value, unsigned int len) {
void set(branch_fn_t fn, const char* value, unsigned int len) _type = cmd_branch;
{ _fn = fn;
_type = cmd_branch; arg1 = -1;
_fn = fn; arg2 = -1;
arg1 = -1; arg3 = -1;
arg2 = -1; farg1 = NULL;
arg3 = -1; farg2 = NULL;
farg1 = NULL; arg_bool = 0;
farg2 = NULL; if (value != NULL) {
arg_bool = 0; if (len > 0) (void)memcpy(_value, value, len);
if (value != NULL) _value[len] = 0;
{ _len = len;
if (len>0) } else {
(void)memcpy(_value, value, len); _value[0] = 0;
_value[len] = 0; _len = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
} }
}
// branch function // branch function
branch_fn_t _fn; branch_fn_t _fn;
// args used by cmd_branch cmds // args used by cmd_branch cmds
int arg1, arg2, arg3; int arg1, arg2, arg3;
number *farg1, *farg2; number *farg1, *farg2;
bool arg_bool; bool arg_bool;
// length of _value, not includiong the terminal '\0' // length of _value, not includiong the terminal '\0'
unsigned int _len; unsigned int _len;
char _value[0]; char _value[0];
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -4,194 +4,244 @@
const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS;
// //
program::keyword_t program::s_keywords[] = program::keyword_t program::s_keywords[] = {
{ // GENERAL
//GENERAL {cmd_undef, "", NULL, "\nGENERAL"},
{ cmd_undef, "", NULL, "\nGENERAL"}, {cmd_keyword, "nop", &program::rpn_nop, "no operation"},
{ cmd_keyword, "nop", &program::rpn_nop, "no operation"}, {cmd_keyword, "help", &program::rpn_help, "this help message"},
{ cmd_keyword, "help", &program::rpn_help, "this help message" }, {cmd_keyword, "h", &program::rpn_help, ""},
{ cmd_keyword, "h", &program::rpn_help, "" }, {cmd_keyword, "?", &program::rpn_help, ""},
{ cmd_keyword, "?", &program::rpn_help, "" }, {cmd_keyword, "quit", &program::rpn_good_bye, "quit software"},
{ cmd_keyword, "quit", &program::rpn_good_bye, "quit software" }, {cmd_keyword, "q", &program::rpn_good_bye, ""},
{ cmd_keyword, "q", &program::rpn_good_bye, "" }, {cmd_keyword, "exit", &program::rpn_good_bye, ""},
{ cmd_keyword, "exit", &program::rpn_good_bye, "" }, {cmd_keyword, "test", &program::rpn_test, ""}, // not seen by user
{ cmd_keyword, "test", &program::rpn_test, "" }, //not seen by user {cmd_keyword, "version", &program::rpn_version, "show rpn version"},
{ cmd_keyword, "version", &program::rpn_version, "show rpn version" }, {cmd_keyword, "uname", &program::rpn_uname,
{ cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string" }, "show rpn complete identification string"},
{ cmd_keyword, "history", &program::rpn_history, "see commands history" }, {cmd_keyword, "history", &program::rpn_history, "see commands history"},
//USUAL OPERATIONS ON REALS AND COMPLEXES // USUAL OPERATIONS ON REALS AND COMPLEXES
{ cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
{ cmd_keyword, "+", &program::rpn_plus, "addition" }, {cmd_keyword, "+", &program::rpn_plus, "addition"},
{ cmd_keyword, "-", &program::rpn_minus, "substraction" }, {cmd_keyword, "-", &program::rpn_minus, "substraction"},
{ cmd_keyword, "chs", &program::rpn_neg , "negation" }, {cmd_keyword, "chs", &program::rpn_neg, "negation"},
{ cmd_keyword, "neg", &program::rpn_neg , "" }, {cmd_keyword, "neg", &program::rpn_neg, ""},
{ cmd_keyword, "*", &program::rpn_mul, "multiplication" }, {cmd_keyword, "*", &program::rpn_mul, "multiplication"},
{ cmd_keyword, "/", &program::rpn_div, "division" }, {cmd_keyword, "/", &program::rpn_div, "division"},
{ cmd_keyword, "inv", &program::rpn_inv, "inverse" }, {cmd_keyword, "inv", &program::rpn_inv, "inverse"},
{ cmd_keyword, "^", &program::rpn_power, "power" }, {cmd_keyword, "^", &program::rpn_power, "power"},
{ cmd_keyword, "pow", &program::rpn_power, "" }, {cmd_keyword, "pow", &program::rpn_power, ""},
{ cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root" }, {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
{ cmd_keyword, "sq", &program::rpn_square, "rpn_square" }, {cmd_keyword, "sq", &program::rpn_square, "rpn_square"},
{ cmd_keyword, "sqr", &program::rpn_square, "" }, {cmd_keyword, "sqr", &program::rpn_square, ""},
{ cmd_keyword, "abs", &program::rpn_abs, "absolute value" }, {cmd_keyword, "abs", &program::rpn_abs, "absolute value"},
{ cmd_keyword, "dec", &program::rpn_dec, "decimal representation" }, {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"},
{ cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation" }, {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"},
{ cmd_keyword, "bin", &program::rpn_bin, "decimal representation" }, {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"},
{ cmd_keyword, "base", &program::rpn_base, "arbitrary base representation" }, {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"},
{ cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0" }, {cmd_keyword, "sign", &program::rpn_sign,
"1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"},
//OPERATIONS ON REALS // OPERATIONS ON REALS
{ cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
{ cmd_keyword, "%", &program::rpn_purcent, "purcent" }, {cmd_keyword, "%", &program::rpn_purcent, "purcent"},
{ cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent" }, {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
{ cmd_keyword, "mod", &program::rpn_modulo, "modulo" }, {cmd_keyword, "mod", &program::rpn_modulo, "modulo"},
{ cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x" }, {cmd_keyword, "fact", &program::rpn_fact,
{ cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number" }, "n! for integer n or Gamma(x+1) for fractional x"},
{ cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number" }, {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"},
{ cmd_keyword, "floor", &program::rpn_floor, "largest number <=" }, {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
{ cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >=" }, {cmd_keyword, "floor", &program::rpn_floor, "largest number <="},
{ cmd_keyword, "ip", &program::rpn_ip, "integer part" }, {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="},
{ cmd_keyword, "fp", &program::rpn_fp, "fractional part" }, {cmd_keyword, "ip", &program::rpn_ip, "integer part"},
{ cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers" }, {cmd_keyword, "fp", &program::rpn_fp, "fractional part"},
{ cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers" }, {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"},
{cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"},
//nOPERATIONS ON COMPLEXES // nOPERATIONS ON COMPLEXES
{ cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
{ cmd_keyword, "re", &program::rpn_re, "complex real part" }, {cmd_keyword, "re", &program::rpn_re, "complex real part"},
{ cmd_keyword, "im", &program::rpn_im, "complex imaginary part" }, {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"},
{ cmd_keyword, "conj", &program::rpn_conj, "complex conjugate" }, {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"},
{ cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians" }, {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"},
{ cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals" }, {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"},
{ cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex" }, {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
{ cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar" }, {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
{ cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian" }, {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
//MODE // MODE
{ cmd_undef, "", NULL, "\nMODE"}, {cmd_undef, "", NULL, "\nMODE"},
{ cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std" }, {cmd_keyword, "std", &program::rpn_std,
{ cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix" }, "standard floating numbers representation. ex: std"},
{ cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci" }, {cmd_keyword, "fix", &program::rpn_fix,
{ cmd_keyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec" }, "fixed point representation. ex: 6 fix"},
{ cmd_keyword, "round", &program::rpn_round, "set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward +inf\", \"toward -inf\", \"away from zero\"] round" }, {cmd_keyword, "sci", &program::rpn_sci,
{ cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default" }, "scientific floating point representation. ex: 20 sci"},
{ cmd_keyword, "type", &program::rpn_type, "show type of stack first entry" }, {cmd_keyword, "prec", &program::rpn_precision,
"set float precision in bits. ex: 256 prec"},
{cmd_keyword, "round", &program::rpn_round,
"set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward "
"+inf\", \"toward -inf\", \"away from zero\"] round"},
{cmd_keyword, "default", &program::rpn_default,
"set float representation and precision to default"},
{cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"},
//TESTS // TESTS
{ cmd_undef, "", NULL, "\nTEST"}, {cmd_undef, "", NULL, "\nTEST"},
{ cmd_keyword, ">", &program::rpn_sup, "binary operator >" }, {cmd_keyword, ">", &program::rpn_sup, "binary operator >"},
{ cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >=" }, {cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="},
{ cmd_keyword, "<", &program::rpn_inf, "binary operator <" }, {cmd_keyword, "<", &program::rpn_inf, "binary operator <"},
{ cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <=" }, {cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="},
{ cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)" }, {cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"},
{ cmd_keyword, "==", &program::rpn_eq , "binary operator == (equal)" }, {cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"},
{ cmd_keyword, "and", &program::rpn_test_and , "boolean operator and" }, {cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"},
{ cmd_keyword, "or", &program::rpn_test_or , "boolean operator or" }, {cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"},
{ cmd_keyword, "xor", &program::rpn_test_xor , "boolean operator xor" }, {cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
{ cmd_keyword, "not", &program::rpn_test_not , "boolean operator not" }, {cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"},
{ cmd_keyword, "same", &program::rpn_same , "boolean operator same (equal)" }, {cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"},
//STACK // STACK
{ cmd_undef, "", NULL, "\nSTACK"}, {cmd_undef, "", NULL, "\nSTACK"},
{ cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries" }, {cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
{ cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry" }, {cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"},
{ cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries" }, {cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"},
{ cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries" }, {cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries"},
{ cmd_keyword, "del", &program::rpn_erase, "drop all stack entries" }, {cmd_keyword, "del", &program::rpn_erase, "drop all stack entries"},
{ cmd_keyword, "erase", &program::rpn_erase, "" }, {cmd_keyword, "erase", &program::rpn_erase, ""},
{ cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries" }, {cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
{ cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry" }, {cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
{ cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries" }, {cmd_keyword, "dup2", &program::rpn_dup2,
{ cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries" }, "duplicate 2 first stack entries"},
{ cmd_keyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack" }, {cmd_keyword, "dupn", &program::rpn_dupn,
{ cmd_keyword, "depth", &program::rpn_depth, "give stack depth" }, "duplicate n first stack entries"},
{ cmd_keyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack" }, {cmd_keyword, "pick", &program::rpn_pick,
{ cmd_keyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position" }, "push a copy of the given stack level onto the stack"},
{ cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack" }, {cmd_keyword, "depth", &program::rpn_depth, "give stack depth"},
{cmd_keyword, "roll", &program::rpn_roll,
"move a stack entry to the top of the stack"},
{cmd_keyword, "rolld", &program::rpn_rolld,
"move the element on top of the stack to a higher stack position"},
{cmd_keyword, "over", &program::rpn_over,
"push a copy of the element in stack level 2 onto the stack"},
//STRING // STRING
{ cmd_undef, "", NULL, "\nSTRING"}, {cmd_undef, "", NULL, "\nSTRING"},
{ cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string" }, {cmd_keyword, "->str", &program::rpn_instr,
{ cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object" }, "convert an object into a string"},
{ cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string" }, {cmd_keyword, "str->", &program::rpn_strout,
{ cmd_keyword, "num", &program::rpn_num, "return ASCII code of the first character of the string in stack level 1 as a real number" }, "convert a string into an object"},
{ cmd_keyword, "size", &program::rpn_strsize, "return the length of the string" }, {cmd_keyword, "chr", &program::rpn_chr,
{ cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2" }, "convert ASCII character code in stack level 1 into a string"},
{ cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3" }, {cmd_keyword, "num", &program::rpn_num,
"return ASCII code of the first character of the string in stack level 1 "
"as a real number"},
{cmd_keyword, "size", &program::rpn_strsize,
"return the length of the string"},
{cmd_keyword, "pos", &program::rpn_strpos,
"seach for the string in level 1 within the string in level 2"},
{cmd_keyword, "sub", &program::rpn_strsub,
"return a substring of the string in level 3"},
//BRANCH // BRANCH
{ cmd_undef, "", NULL, "\nBRANCH"}, {cmd_undef, "", NULL, "\nBRANCH"},
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "if <test-instruction> then <true-instructions> else <false-instructions> end" }, {cmd_branch, "if", (program_fn_t)&program::rpn_if,
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if" }, "if <test-instruction> then <true-instructions> else <false-instructions> "
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" }, "end"},
{ cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" }, {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"},
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step" }, {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"},
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "<start> <end> for <variable> <instructions> next|<step> step" }, {cmd_branch, "end", (program_fn_t)&program::rpn_end,
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" }, "used with various branch instructions"},
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for" }, {cmd_branch, "start", (program_fn_t)&program::rpn_start,
{ cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, <test-instruction> <true-instruction> ift" }, "<start> <end> start <instructions> next|<step> step"},
{ cmd_keyword, "ifte",&program::rpn_ifte, "similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte" }, {cmd_branch, "for", (program_fn_t)&program::rpn_for,
{ cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end" }, "<start> <end> for <variable> <instructions> next|<step> step"},
{ cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do" }, {cmd_branch, "next", (program_fn_t)&program::rpn_next,
{ cmd_branch, "unti", (program_fn_t)&program::rpn_until, "" }, "used with start and for"},
{ cmd_branch, "while", (program_fn_t)&program::rpn_while, "while <test-instruction> repeat <loop-instructions> end" }, {cmd_branch, "step", (program_fn_t)&program::rpn_step,
{ cmd_branch, "whil", (program_fn_t)&program::rpn_while, "" }, "used with start and for"},
{ cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while" }, {cmd_keyword, "ift", &program::rpn_ift,
{ cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, "" }, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
{cmd_keyword, "ifte", &program::rpn_ifte,
"similar to if-then-else-end, <test-instruction> <true-instruction> "
"<false-instruction> ifte"},
{cmd_branch, "do", (program_fn_t)&program::rpn_do,
"do <instructions> until <condition> end"},
{cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"},
{cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""},
{cmd_branch, "while", (program_fn_t)&program::rpn_while,
"while <test-instruction> repeat <loop-instructions> end"},
{cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""},
{cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat,
"used with while"},
{cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""},
//STORE // STORE
{ cmd_undef, "", NULL, "\nSTORE"}, {cmd_undef, "", NULL, "\nSTORE"},
{ cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto" }, {cmd_keyword, "sto", &program::rpn_sto,
{ cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl" }, "store a variable. ex: 1 'name' sto"},
{ cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge" }, {cmd_keyword, "rcl", &program::rpn_rcl,
{ cmd_keyword, "vars", &program::rpn_vars, "list all variables" }, "recall a variable. ex: 'name' rcl"},
{ cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables" }, {cmd_keyword, "purge", &program::rpn_purge,
{ cmd_keyword, "edit", &program::rpn_edit, "edit a variable content" }, "delete a variable. ex: 'name' purge"},
{ cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+" }, {cmd_keyword, "vars", &program::rpn_vars, "list all variables"},
{ cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-" }, {cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"},
{ cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*" }, {cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"},
{ cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/" }, {cmd_keyword, "sto+", &program::rpn_stoadd,
{ cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg" }, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
{ cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv" }, {cmd_keyword, "sto-", &program::rpn_stosub,
"substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
{cmd_keyword, "sto*", &program::rpn_stomul,
"multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
{cmd_keyword, "sto/", &program::rpn_stodiv,
"divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
{cmd_keyword, "sneg", &program::rpn_stoneg,
"negate a variable. ex: 'name' sneg"},
{cmd_keyword, "sinv", &program::rpn_stoinv,
"inverse a variable. ex: 1 'name' sinv"},
//PROGRAM // PROGRAM
{ cmd_undef, "", NULL, "\nPROGRAM"}, {cmd_undef, "", NULL, "\nPROGRAM"},
{ cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" }, {cmd_keyword, "eval", &program::rpn_eval,
{ cmd_branch, "->", (program_fn_t)&program::rpn_inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> >>" }, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
{cmd_branch, "->", (program_fn_t)&program::rpn_inprog,
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
">>"},
//TRIG ON REALS AND COMPLEXES // TRIG ON REALS AND COMPLEXES
{ cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
{ cmd_keyword, "pi", &program::rpn_pi, "pi constant" }, {cmd_keyword, "pi", &program::rpn_pi, "pi constant"},
{ cmd_keyword, "sin", &program::rpn_sin, "sinus" }, {cmd_keyword, "sin", &program::rpn_sin, "sinus"},
{ cmd_keyword, "asin", &program::rpn_asin, "arg sinus" }, {cmd_keyword, "asin", &program::rpn_asin, "arg sinus"},
{ cmd_keyword, "cos", &program::rpn_cos , "cosinus" }, {cmd_keyword, "cos", &program::rpn_cos, "cosinus"},
{ cmd_keyword, "acos", &program::rpn_acos, "arg cosinus" }, {cmd_keyword, "acos", &program::rpn_acos, "arg cosinus"},
{ cmd_keyword, "tan", &program::rpn_tan, "tangent" }, {cmd_keyword, "tan", &program::rpn_tan, "tangent"},
{ cmd_keyword, "atan", &program::rpn_atan, "arg tangent" }, {cmd_keyword, "atan", &program::rpn_atan, "arg tangent"},
{ cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians" }, {cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
{ cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees" }, {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
//LOGS ON REALS AND COMPLEXES // LOGS ON REALS AND COMPLEXES
{ cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
{ cmd_keyword, "e", &program::rpn_e, "Euler constant" }, {cmd_keyword, "e", &program::rpn_e, "Euler constant"},
{ cmd_keyword, "ln", &program::rpn_ln, "logarithm base e" }, {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"},
{ cmd_keyword, "log", &program::rpn_ln, "" }, {cmd_keyword, "log", &program::rpn_ln, ""},
{ cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0" }, {cmd_keyword, "lnp1", &program::rpn_lnp1,
{ cmd_keyword, "exp", &program::rpn_exp, "exponential" }, "ln(1+x) which is useful when x is close to 0"},
{ cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0" }, {cmd_keyword, "exp", &program::rpn_exp, "exponential"},
{ cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10" }, {cmd_keyword, "expm", &program::rpn_expm,
{ cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10" }, "exp(x)-1 which is useful when x is close to 0"},
{ cmd_keyword, "exp10", &program::rpn_alog10, "" }, {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"},
{ cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2" }, {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"},
{ cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2" }, {cmd_keyword, "exp10", &program::rpn_alog10, ""},
{ cmd_keyword, "exp2", &program::rpn_alog2, "" }, {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"},
{ cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine" }, {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"},
{ cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine" }, {cmd_keyword, "exp2", &program::rpn_alog2, ""},
{ cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine" }, {cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
{ cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine" }, {cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
{ cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent" }, {cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine"},
{ cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent" }, {cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"},
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
// end // end
{ cmd_max, "", NULL, "" }, {cmd_max, "", NULL, ""},
}; };

File diff suppressed because it is too large Load diff

View file

@ -1,309 +1,285 @@
// //
int rpn_if(branch& myobj) int rpn_if(branch& myobj) {
{ // myobj.arg1 = 'if' condition evaluation value
// myobj.arg1 = 'if' condition evaluation value MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0) if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
myobj.arg1 = 1; myobj.arg1 = 1;
else else
myobj.arg1 = 0; myobj.arg1 = 0;
(void)_stack->pop_back(); (void)_stack->pop_back();
return -1; return -1;
} }
int rpn_then(branch& myobj) int rpn_then(branch& myobj) {
{ // myobj.arg1 = index of then + 1
// myobj.arg1 = index of then + 1 // myobj.arg2 = index of else + 1 or end + 1
// myobj.arg2 = index of else + 1 or end + 1 // myobj.arg3 = index of if
// myobj.arg3 = index of if // if condition is true -> arg1 (= jump to then + 1)
// if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1)
// else -> arg2 (= jump to else + 1 or end + 1) branch* if_cmd = (branch*)seq_obj(myobj.arg3);
branch* if_cmd = (branch*)seq_obj(myobj.arg3); if (if_cmd->arg1 == 1)
if (if_cmd->arg1 == 1) return myobj.arg1;
return myobj.arg1; else
else return myobj.arg2;
return myobj.arg2;
} }
int rpn_else(branch& myobj) int rpn_else(branch& myobj) {
{ // myobj.arg1 = index of else + 1
// myobj.arg1 = index of else + 1 // myobj.arg2 = index of end + 1
// myobj.arg2 = index of end + 1 // myobj.arg3 = index of if
// myobj.arg3 = index of if // if condition was false -> arg1 (= jump to else + 1)
// if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1)
// if condition was true -> arg2 (= jump to end + 1) branch* if_cmd = (branch*)seq_obj(myobj.arg3);
branch* if_cmd = (branch*)seq_obj(myobj.arg3); if (if_cmd->arg1 == 1)
if (if_cmd->arg1 == 1) return myobj.arg2;
return myobj.arg2; else
else return myobj.arg1;
return myobj.arg1;
} }
int rpn_end(branch& myobj) int rpn_end(branch& myobj) {
{ int ret = -1;
int ret = -1;
// arg1 = index of do+1 in case of do..unti..end
if (myobj.arg1 != -1)
{
// in a template do..unti..end
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
// check arg
number* arg = (number*)_stack->pop_back();
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
ret = myobj.arg1;
}
// arg2 = index of while+1 in case of while..repeat..end
else if (myobj.arg2 != -1)
ret = myobj.arg2;
return ret;
}
int rpn_do(branch& myobj)
{
// nothing
return -1;
}
int rpn_until(branch& myobj)
{
// nothing
return -1;
}
//
void rpn_ift(void)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
// check ift arg
// arg is true if number != 0 or if is nan or +/-inf
number* testee = ((number*)_stack->get_obj(1));
if (!mpfr_zero_p(testee->_value.mpfr))
{
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
(void)_stack->pop_back(2);
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
(void)_calc_stack.pop_back();
}
else
(void)_stack->pop_back(2);
}
void rpn_ifte(void)
{
MIN_ARGUMENTS(3);
ARG_MUST_BE_OF_TYPE(2, cmd_number);
// check ifte arg
// arg is true if number != 0 or if is nan or +/-inf
number* testee = ((number*)_stack->get_obj(2));
if (!mpfr_zero_p(testee->_value.mpfr))
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack));
else
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
(void)_stack->pop_back(3);
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
(void)_calc_stack.pop_back();
}
//
int rpn_while(branch& myobj)
{
// nothing
return -1;
}
int rpn_repeat(branch& myobj)
{
int ret = -1;
// arg1 = index of do+1 in case of do..unti..end
if (myobj.arg1 != -1) {
// in a template do..unti..end
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
// check arg // check arg
// myobj.arg1 is end+1
number* arg = (number*)_stack->pop_back(); number* arg = (number*)_stack->pop_back();
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
ret = myobj.arg1; }
// arg2 = index of while+1 in case of while..repeat..end
else if (myobj.arg2 != -1)
ret = myobj.arg2;
return ret; return ret;
} }
int rpn_start(branch& myobj) int rpn_do(branch& myobj) {
{ // nothing
int ret = -1; return -1;
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
// farg2 = last value of start command
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
myobj.farg2 = (number*)_calc_stack.back();
_stack->pop_back();
// farg1 = first value of start command
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
myobj.farg1 = (number*)_calc_stack.back();
_stack->pop_back();
// test value
if (myobj.farg1->_value > myobj.farg2->_value)
// last boundary lower than first boundary
// -> next command shall be after 'next'
// arg2 holds index of 'next'
ret = myobj.arg2 + 1;
return ret;
} }
int rpn_for(branch& myobj) int rpn_until(branch& myobj) {
{ // nothing
int ret; return -1;
}
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error); //
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); void rpn_ift(void) {
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
symbol* sym = ((symbol*)seq_obj(myobj.arg1)); // check ift arg
// arg is true if number != 0 or if is nan or +/-inf
number* testee = ((number*)_stack->get_obj(1));
// farg2 = last value of for command if (!mpfr_zero_p(testee->_value.mpfr)) {
// arg1 = index of symbol to increase CHECK_MPFR(
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
myobj.farg2 = (number*)_calc_stack.back(); (void)_stack->pop_back(2);
_stack->pop_back();
// farg1 = first value of for command CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1,
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); *_stack));
myobj.farg1 = (number*)_calc_stack.back(); (void)_calc_stack.pop_back();
_stack->pop_back(); } else
(void)_stack->pop_back(2);
}
// test value void rpn_ifte(void) {
if (myobj.farg1->_value > myobj.farg2->_value) MIN_ARGUMENTS(3);
// last boundary lower than first boundary ARG_MUST_BE_OF_TYPE(2, cmd_number);
// -> next command shall be after 'next'
// arg2 holds index of 'next' // check ifte arg
ret = myobj.arg2 + 1; // arg is true if number != 0 or if is nan or +/-inf
number* testee = ((number*)_stack->get_obj(2));
if (!mpfr_zero_p(testee->_value.mpfr))
CHECK_MPFR(
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack));
else
CHECK_MPFR(
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
(void)_stack->pop_back(3);
CHECK_MPFR(
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack));
(void)_calc_stack.pop_back();
}
//
int rpn_while(branch& myobj) {
// nothing
return -1;
}
int rpn_repeat(branch& myobj) {
int ret = -1;
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
// check arg
// myobj.arg1 is end+1
number* arg = (number*)_stack->pop_back();
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
return ret;
}
int rpn_start(branch& myobj) {
int ret = -1;
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
// farg2 = last value of start command
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
myobj.farg2 = (number*)_calc_stack.back();
_stack->pop_back();
// farg1 = first value of start command
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
myobj.farg1 = (number*)_calc_stack.back();
_stack->pop_back();
// test value
if (myobj.farg1->_value > myobj.farg2->_value)
// last boundary lower than first boundary
// -> next command shall be after 'next'
// arg2 holds index of 'next'
ret = myobj.arg2 + 1;
return ret;
}
int rpn_for(branch& myobj) {
int ret;
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
// farg2 = last value of for command
// arg1 = index of symbol to increase
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
myobj.farg2 = (number*)_calc_stack.back();
_stack->pop_back();
// farg1 = first value of for command
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
myobj.farg1 = (number*)_calc_stack.back();
_stack->pop_back();
// test value
if (myobj.farg1->_value > myobj.farg2->_value)
// last boundary lower than first boundary
// -> next command shall be after 'next'
// arg2 holds index of 'next'
ret = myobj.arg2 + 1;
else {
// store symbol with first value
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
ret = myobj.arg1 + 1;
}
return ret;
}
int rpn_next(branch& myobj) {
// arg1 = index of start or for command in program
// farg1 = current count
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
if (!myobj.arg_bool) {
myobj.arg_bool = true;
myobj.farg1 = start_or_for->farg1;
}
// increment then test
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL,
MPFR_DEFAULT_RND);
// for command: increment symbol too
if (start_or_for->arg1 != -1) {
object* obj;
unsigned int size;
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// increase symbol variable
_local_heap.replace_value(string(var->_value), myobj.farg1,
myobj.farg1->size());
}
// test value
if (myobj.farg1->_value > start_or_for->farg2->_value) {
// end of loop
myobj.arg_bool = false; // init again next time
_calc_stack.pop_back(2);
return -1;
} else {
// for command: next instruction will be after symbol variable
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
// start command: next instruction will be after start command
else else
{ return myobj.arg1 + 1;
// store symbol with first value }
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
ret = myobj.arg1 + 1;
}
return ret;
} }
int rpn_next(branch& myobj) int rpn_step(branch& myobj) {
{ int ret;
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
number* step = (number*)_stack->pop_back();
// end of loop if step is negative or zero
if (mpfr_cmp_d(step->_value.mpfr, 0.0) <= 0)
ret = -1;
else {
// arg1 = index of start or for command in program // arg1 = index of start or for command in program
// farg1 = current count // farg1 = current count
branch* start_or_for = (branch*)seq_obj(myobj.arg1); branch* start_or_for = (branch*)seq_obj(myobj.arg1);
if (! myobj.arg_bool) if (!myobj.arg_bool) {
{ myobj.arg_bool = true;
myobj.arg_bool = true; myobj.farg1 = start_or_for->farg1;
myobj.farg1 = start_or_for->farg1;
} }
// increment then test // increment then test
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL, MPFR_DEFAULT_RND); mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr,
step->_value.mpfr, MPFR_DEFAULT_RND);
// for command: increment symbol too // for command: increment symbol too
if (start_or_for->arg1 != -1) if (start_or_for->arg1 != -1) {
{ object* obj;
object* obj; unsigned int size;
unsigned int size; symbol* var = (symbol*)seq_obj(start_or_for->arg1);
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// increase symbol variable // increase symbol variable
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); _local_heap.replace_value(string(var->_value), myobj.farg1,
myobj.farg1->size());
} }
//test value // test loop value is out of range
if (myobj.farg1->_value > start_or_for->farg2->_value) if (myobj.farg1->_value > start_or_for->farg2->_value) {
{ // end of loop
// end of loop myobj.arg_bool = false; // init again next time
myobj.arg_bool = false;// init again next time _calc_stack.pop_back(2);
_calc_stack.pop_back(2); ret = -1;
return -1; } else {
} // for command: next instruction will be after symbol variable
else if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
{ // start command: next instruction will be after start command
// for command: next instruction will be after symbol variable else
if (start_or_for->arg1 != -1) ret = myobj.arg1 + 1;
return start_or_for->arg1 + 1;
// start command: next instruction will be after start command
else
return myobj.arg1 + 1;
} }
} }
int rpn_step(branch& myobj) return ret;
{
int ret;
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
number* step = (number*)_stack->pop_back();
// end of loop if step is negative or zero
if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0)
ret = -1;
else
{
// arg1 = index of start or for command in program
// farg1 = current count
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
if (! myobj.arg_bool)
{
myobj.arg_bool = true;
myobj.farg1 = start_or_for->farg1;
}
// increment then test
mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEFAULT_RND);
// for command: increment symbol too
if (start_or_for->arg1 != -1)
{
object* obj;
unsigned int size;
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// increase symbol variable
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
}
// test loop value is out of range
if (myobj.farg1->_value > start_or_for->farg2->_value)
{
// end of loop
myobj.arg_bool = false;// init again next time
_calc_stack.pop_back(2);
ret = -1;
}
else
{
// for command: next instruction will be after symbol variable
if (start_or_for->arg1 != -1)
ret = start_or_for->arg1 + 1;
// start command: next instruction will be after start command
else
ret = myobj.arg1 + 1;
}
}
return ret;
} }

View file

@ -1,130 +1,146 @@
void rpn_re() void rpn_re() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->re()->mpfr, floating_t::s_mpfr_rnd)); _stack->pop_back();
_calc_stack.pop_back();
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set(re->_value.mpfr,
((complex*)_calc_stack.get_obj(0))->re()->mpfr,
floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
} }
void rpn_im() void rpn_im() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->im()->mpfr, floating_t::s_mpfr_rnd)); _stack->pop_back();
_calc_stack.pop_back();
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set(im->_value.mpfr,
((complex*)_calc_stack.get_obj(0))->im()->mpfr,
floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
} }
void rpn_arg() void rpn_arg() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
// calc atan2(x/y) // calc atan2(x/y)
complex* cplx = (complex*)_stack->pop_back(); complex* cplx = (complex*)_stack->pop_back();
number* num = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); number* num =
(number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr,
floating_t::s_mpfr_rnd));
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack); stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
_calc_stack.pop_back(); _calc_stack.pop_back();
} }
void rpn_conj() void rpn_conj() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
complex* cplx = (complex*)_stack->back(); complex* cplx = (complex*)_stack->back();
CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(
mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
} }
void rpn_r2c() void rpn_r2c() {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
_stack->pop_back();
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex); stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.get_obj(1))->_value.mpfr, floating_t::s_mpfr_rnd)); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd)); _stack->pop_back();
_calc_stack.pop_back(2); _stack->pop_back();
complex* cplx =
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
CHECK_MPFR(mpfr_set(cplx->re()->mpfr,
((number*)_calc_stack.get_obj(1))->_value.mpfr,
floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_set(cplx->im()->mpfr,
((number*)_calc_stack.get_obj(0))->_value.mpfr,
floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
} }
void rpn_c2r() void rpn_c2r() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back(); _stack->pop_back();
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set(re->_value.mpfr,
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, floating_t::s_mpfr_rnd)); ((complex*)_calc_stack.back())->re()->mpfr,
_calc_stack.pop_back(); floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_set(im->_value.mpfr,
((complex*)_calc_stack.back())->im()->mpfr,
floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
} }
void rpn_r2p() void rpn_r2p() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
rpn_dup(); rpn_dup();
rpn_dup(); rpn_dup();
rpn_arg(); rpn_arg();
complex* cplx = (complex*)_stack->get_obj(1); complex* cplx = (complex*)_stack->get_obj(1);
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr,
_stack->pop_back(); floating_t::s_mpfr_rnd));
_stack->pop_back();
rpn_swap();
rpn_abs(); rpn_swap();
cplx = (complex*)_stack->get_obj(1); rpn_abs();
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); cplx = (complex*)_stack->get_obj(1);
_stack->pop_back(); CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd));
_stack->pop_back();
} }
void rpn_p2r() void rpn_p2r() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_calc_stack.allocate_back(number::calc_size(), cmd_number); _calc_stack.allocate_back(number::calc_size(), cmd_number);
// assert complex is polar
complex* rhotheta = (complex*)_calc_stack.get_obj(1);
number* tmp = (number*)_calc_stack.get_obj(0);
complex* result = (complex*)_stack->back();
//calc cos(theta) // assert complex is polar
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd)); complex* rhotheta = (complex*)_calc_stack.get_obj(1);
CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); number* tmp = (number*)_calc_stack.get_obj(0);
complex* result = (complex*)_stack->back();
//calc rcos(theta) // calc cos(theta)
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(
mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
//calc sin(theta) // calc rcos(theta)
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr,
CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); tmp->_value.mpfr, floating_t::s_mpfr_rnd));
//calc rsin(theta) // calc sin(theta)
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(
mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
// calc rsin(theta)
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr,
tmp->_value.mpfr, floating_t::s_mpfr_rnd));
} }

View file

@ -1,230 +1,209 @@
// //
void rpn_nop() void rpn_nop() {
{ // nop
// nop
} }
void rpn_good_bye() void rpn_good_bye() { ERR_CONTEXT(ret_good_bye); }
{
ERR_CONTEXT(ret_good_bye);
}
void rpn_help() void rpn_help() {
{ // software name
// software name printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
// description // description
printf("%s\n\n", description); printf("%s\n\n", description);
// syntax // syntax
printf("%s\n", syntax); printf("%s\n", syntax);
// keywords // keywords
unsigned int i = 0; unsigned int i = 0;
while(s_keywords[i].type != cmd_max) while (s_keywords[i].type != cmd_max) {
{ if (s_keywords[i].comment.size() != 0) {
if (s_keywords[i].comment.size() != 0) // titles in bold
{ if (s_keywords[i].type == cmd_undef) printf(ATTR_BOLD);
// titles in bold // show title or keyword + comment
if (s_keywords[i].type==cmd_undef) printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
printf(ATTR_BOLD); if (s_keywords[i].type == cmd_undef) printf(ATTR_OFF);
// show title or keyword + comment
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
if (s_keywords[i].type==cmd_undef)
printf(ATTR_OFF);
}
i++;
} }
printf("\n"); i++;
}
printf("\n");
// show mode // show mode
printf("Current float mode is "); printf("Current float mode is ");
switch(number::s_mode) switch (number::s_mode) {
{ case number::std:
case number::std: printf("'std'"); break; printf("'std'");
case number::fix: printf("'fix'"); break; break;
case number::sci: printf("'sci'"); break; case number::fix:
default: printf("unknown"); break; printf("'fix'");
break;
case number::sci:
printf("'sci'");
break;
default:
printf("unknown");
break;
}
printf(" with %d digits after the decimal point\n", number::s_decimal_digits);
// 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 base_digits_from_bit_precision(int base, int bit_precision) {
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
}
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_decimal_digits(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 = 0.0;
if (precision < prec_min || precision > prec_max) ret = false;
return ret;
}
void rpn_std() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits)) {
// set mode, decimal digits and print format
number::s_mode = number::std;
number::s_decimal_digits = (int)digits;
number::s_mpfr_printf_format =
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
} else
ERR_CONTEXT(ret_out_of_range);
}
void rpn_fix() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits)) {
// set mode, decimal digits and print format
number::s_mode = number::fix;
number::s_decimal_digits = (int)digits;
number::s_mpfr_printf_format =
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
} else
ERR_CONTEXT(ret_out_of_range);
}
void rpn_sci() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits)) {
// set mode, decimal digits and print format
number::s_mode = number::sci;
number::s_decimal_digits = (int)digits;
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() {
// allocate and set object
unsigned int naked_entry_len = strlen(version);
ostring* str = (ostring*)_stack->allocate_back(
sizeof(ostring) + naked_entry_len + 1, cmd_string);
str->set(version, naked_entry_len);
}
void rpn_uname() {
// allocate and set object
unsigned int naked_entry_len = strlen(uname);
ostring* str = (ostring*)_stack->allocate_back(
sizeof(ostring) + naked_entry_len + 1, cmd_string);
str->set(uname, naked_entry_len);
}
void rpn_history() {
// see command history on stdout
int index = 0;
char* line = linenoiseHistoryLine(index);
while (line != NULL) {
cout << line << endl;
free(line);
line = linenoiseHistoryLine(++index);
}
}
void rpn_type() {
MIN_ARGUMENTS(1);
int type = _stack->pop_back()->_type;
if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef;
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
unsigned int size = sizeof(symbol) + string_size + 1;
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
typ->set(object::s_cmd_type_string[type], string_size);
}
void rpn_default() { program::apply_default(); }
void rpn_precision() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// set precision
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr,
floating_t::s_mpfr_rnd);
if (prec >= (unsigned long)MPFR_PREC_MIN &&
prec <= (unsigned long)MPFR_PREC_MAX) {
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 =
base_digits_from_bit_precision(10, floating_t::s_mpfr_prec);
number::s_mpfr_printf_format =
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
} }
printf(" with %d digits after the decimal point\n", number::s_decimal_digits); } else
ERR_CONTEXT(ret_out_of_range);
// 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 base_digits_from_bit_precision(int base, int bit_precision) void rpn_round() {
{ MIN_ARGUMENTS(1);
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1; ARG_MUST_BE_OF_TYPE(0, cmd_string);
}
string make_digit_format(int decimal_digits, const char* printf_format) ostring* str = (ostring*)_stack->pop_back();
{ bool done = false;
stringstream ss; for (int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++) {
ss << MPFR_FORMAT_BEG; if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value) {
ss << number::s_decimal_digits; floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
ss << printf_format; done = true;
return ss.str();
}
bool check_decimal_digits(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 = 0.0;
if (precision < prec_min || precision > prec_max)
ret = false;
return ret;
}
void rpn_std()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits))
{
// set mode, decimal digits and print format
number::s_mode = number::std;
number::s_decimal_digits = (int)digits;
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
} }
else }
ERR_CONTEXT(ret_out_of_range); if (!done) ERR_CONTEXT(ret_out_of_range);
}
void rpn_fix()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits))
{
// set mode, decimal digits and print format
number::s_mode = number::fix;
number::s_decimal_digits = (int)digits;
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
}
else
ERR_CONTEXT(ret_out_of_range);
}
void rpn_sci()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
double digits = double(((number*)_stack->pop_back())->_value);
if (check_decimal_digits(digits))
{
// set mode, decimal digits and print format
number::s_mode = number::sci;
number::s_decimal_digits = (int)digits;
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()
{
// allocate and set object
unsigned int naked_entry_len = strlen(version);
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
str->set(version, naked_entry_len);
}
void rpn_uname()
{
// allocate and set object
unsigned int naked_entry_len = strlen(uname);
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
str->set(uname, naked_entry_len);
}
void rpn_history()
{
//see command history on stdout
int index = 0;
char* line = linenoiseHistoryLine(index);
while(line != NULL)
{
cout<<line<<endl;
free(line);
line = linenoiseHistoryLine(++index);
}
}
void rpn_type()
{
MIN_ARGUMENTS(1);
int type = _stack->pop_back()->_type;
if (type < 0 || type >= (int)cmd_max)
type = (int)cmd_undef;
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
unsigned int size = sizeof(symbol)+string_size+1;
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
typ->set(object::s_cmd_type_string[type], string_size);
}
void rpn_default()
{
program::apply_default();
}
void rpn_precision()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
//set precision
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
if (prec>=(unsigned long)MPFR_PREC_MIN && prec<=(unsigned long)MPFR_PREC_MAX)
{
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 = base_digits_from_bit_precision(10, 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);
}
void rpn_round()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
ostring* str = (ostring*)_stack->pop_back();
bool done = false;
for(int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++)
{
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value)
{
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
done = true;
}
}
if (!done)
ERR_CONTEXT(ret_out_of_range);
} }

View file

@ -1,377 +1,337 @@
void rpn_e(void) void rpn_e(void) {
{ number* euler =
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
euler->_value = 1L; euler->_value = 1L;
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(
mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
} }
void rpn_log10() void rpn_log10() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ // log10(z)=ln(z)/ln(10)
//log10(z)=ln(z)/ln(10) rpn_ln();
rpn_ln();
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* ten =
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_ln(); CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_div(); rpn_ln();
} rpn_div();
else } else
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_alog10() void rpn_alog10() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; number* ten =
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_ln(); rpn_ln();
rpn_mul(); rpn_mul();
rpn_exp(); rpn_exp();
} }
} }
void rpn_log2() void rpn_log2() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ // log2(z)=ln(z)/ln(2)
//log2(z)=ln(z)/ln(2) rpn_ln();
rpn_ln();
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* two =
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_ln(); CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_div(); rpn_ln();
} rpn_div();
else } else
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_alog2() void rpn_alog2() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; number* two =
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_ln(); rpn_ln();
rpn_mul(); rpn_mul();
rpn_exp(); rpn_exp();
} }
} }
void rpn_ln() void rpn_ln() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ number* left = (number*)_stack->back();
number* left = (number*)_stack->back();
// x<0 -> ln(x) = ln(-x)+i*pi // x<0 -> ln(x) = ln(-x)+i*pi
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) {
{ stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); _stack->pop_back();
_stack->pop_back(); left = (number*)_calc_stack.back();
left = (number*)_calc_stack.back();
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex); complex* cplx =
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr,
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd)); floating_t::s_mpfr_rnd));
_calc_stack.pop_back(); CHECK_MPFR(
} mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
else CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back();
} } else
else if (_stack->get_type(0) == cmd_complex) CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr,
{ floating_t::s_mpfr_rnd));
// ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y) } else if (_stack->get_type(0) == cmd_complex) {
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); // ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y)
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re(); floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im(); floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im(); floating_t* im = ((complex*)_stack->get_obj(0))->im();
// 1. atan(x/y) // 1. atan(x/y)
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
// 2. 0.5*ln(x*x+y*y) // 2. 0.5*ln(x*x+y*y)
CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(); _calc_stack.pop_back();
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_exp() void rpn_exp() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // exp(x)*(cos(y)+i sin(y))
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
{
// exp(x)*(cos(y)+i sin(y))
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re(); floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im(); floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im(); floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(); _calc_stack.pop_back();
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_expm() void rpn_expm() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ // exp(x)-1
//exp(x)-1 rpn_exp();
rpn_exp();
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number); number* one =
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_minus(); CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
} rpn_minus();
else } else
ERR_CONTEXT(ret_bad_operand_type); ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_lnp1() void rpn_lnp1() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
{ // ln(x+1)
//ln(x+1) number* one =
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_plus(); rpn_plus();
rpn_ln(); rpn_ln();
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_sinh() void rpn_sinh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
{
// sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; floating_t* tmp =
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); ->_value;
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im(); floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2); _calc_stack.pop_back(2);
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_asinh() void rpn_asinh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // asinh(z)=ln(z+sqrt(1+z*z))
else if (_stack->get_type(0) == cmd_complex) rpn_dup();
{ rpn_square();
// asinh(z)=ln(z+sqrt(1+z*z)) number* num =
rpn_dup(); (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_square(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_plus();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_squareroot();
rpn_plus(); rpn_plus();
rpn_squareroot(); rpn_ln();
rpn_plus(); } else
rpn_ln(); ERR_CONTEXT(ret_bad_operand_type);
}
else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_cosh() void rpn_cosh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
{
// acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; floating_t* tmp =
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); ->_value;
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im(); floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2); _calc_stack.pop_back(2);
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_acosh() void rpn_acosh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // acosh(z)=ln(z+sqrt(z+1)sqrt(z-1))
else if (_stack->get_type(0) == cmd_complex) rpn_dup();
{ number* num =
// acosh(z)=ln(z+sqrt(z+1)sqrt(z-1)) (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_dup(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_plus();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_dup();
rpn_plus(); num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_dup(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_minus();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_mul();
rpn_minus(); rpn_squareroot();
rpn_mul(); rpn_plus();
rpn_squareroot(); rpn_ln();
rpn_plus(); } else
rpn_ln(); ERR_CONTEXT(ret_bad_operand_type);
}
else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_tanh() void rpn_tanh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
else if (_stack->get_type(0) == cmd_complex) rpn_dup();
{
// tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
rpn_dup();
floating_t* x = ((complex*)_stack->get_obj(1))->re(); floating_t* x = ((complex*)_stack->get_obj(1))->re();
floating_t* y = ((complex*)_stack->get_obj(1))->im(); floating_t* y = ((complex*)_stack->get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(1))->re(); floating_t* re = ((complex*)_stack->get_obj(1))->re();
floating_t* im = ((complex*)_stack->get_obj(1))->im(); floating_t* im = ((complex*)_stack->get_obj(1))->im();
CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_div(); rpn_div();
} } else
else ERR_CONTEXT(ret_bad_operand_type);
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_atanh() void rpn_atanh() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // atanh(z)=0.5*ln((1+z)/(1-z))
else if (_stack->get_type(0) == cmd_complex) rpn_dup();
{ number* num =
// atanh(z)=0.5*ln((1+z)/(1-z)) (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_dup(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_plus();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_swap();
rpn_plus(); num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_swap(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_minus();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_neg();
rpn_minus(); rpn_div();
rpn_neg(); rpn_ln();
rpn_div(); num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
rpn_ln(); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); rpn_mul();
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); } else
rpn_mul(); ERR_CONTEXT(ret_bad_operand_type);
}
else
ERR_CONTEXT(ret_bad_operand_type);
} }

View file

@ -1,167 +1,139 @@
// //
bool find_variable(string& variable, object*& obj, unsigned int& size) bool find_variable(string& variable, object*& obj, unsigned int& size) {
{ bool found = false;
bool found = false; program* parent = _parent_prog;
program* parent = _parent_prog;
// find variable in local heap, parens heaps, global heap // find variable in local heap, parens heaps, global heap
if (_local_heap.get(variable, obj, size)) if (_local_heap.get(variable, obj, size))
found = true;
else {
while (parent != NULL) {
if (parent->_local_heap.get(variable, obj, size)) {
found = true; found = true;
else break;
{ }
while(parent != NULL) parent = parent->_parent_prog;
{
if (parent->_local_heap.get(variable, obj, size))
{
found = true;
break;
}
parent = parent->_parent_prog;
}
if (!found)
{
if (_heap->get(variable, obj, size))
found = true;
}
} }
if (!found) {
return found; if (_heap->get(variable, obj, size)) found = true;
}
}
return found;
} }
void rpn_eval(void) void rpn_eval(void) {
{ bool run_prog = false;
bool run_prog = false; string prog_text;
string prog_text;
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
if (IS_ARG_TYPE(0, cmd_symbol)) if (IS_ARG_TYPE(0, cmd_symbol)) {
{ // recall a variable
// recall a variable object* obj;
object* obj; unsigned int size;
unsigned int size; string variable(((symbol*)_stack->back())->_value);
string variable(((symbol*)_stack->back())->_value);
// if variable holds a program, run this program
// if variable holds a program, run this program if (find_variable(variable, obj, size)) {
if (find_variable(variable, obj, size)) if (obj->_type == cmd_program) {
{ prog_text = ((oprogram*)obj)->_value;
if (obj->_type == cmd_program) (void)_stack->pop_back();
{
prog_text = ((oprogram*)obj)->_value;
(void)_stack->pop_back();
run_prog = true;
}
else
{
// else recall this variable (i.e. stack its content)
(void)_stack->pop_back();
stack::copy_and_push_back(obj, *_stack, size);
}
}
else
ERR_CONTEXT(ret_unknown_variable);
}
else if (IS_ARG_TYPE(0, cmd_program))
{
// eval a program
prog_text = ((oprogram*)_stack->pop_back())->_value;
run_prog = true; run_prog = true;
} } else {
else // else recall this variable (i.e. stack its content)
ERR_CONTEXT(ret_bad_operand_type); (void)_stack->pop_back();
stack::copy_and_push_back(obj, *_stack, size);
}
} else
ERR_CONTEXT(ret_unknown_variable);
} else if (IS_ARG_TYPE(0, cmd_program)) {
// eval a program
prog_text = ((oprogram*)_stack->pop_back())->_value;
run_prog = true;
} else
ERR_CONTEXT(ret_bad_operand_type);
// run prog if any // run prog if any
if (run_prog) if (run_prog) {
{ program prog(this);
program prog(this);
// make program from entry // make program from entry
if (program::parse(prog_text.c_str(), prog) == ret_ok) if (program::parse(prog_text.c_str(), prog) == ret_ok) {
{ // run it
// run it prog.run(*_stack, *_heap);
prog.run(*_stack, *_heap);
}
} }
}
} }
// carefull, this not a command but a branch // carefull, this not a command but a branch
int rpn_inprog(branch& myobj) int rpn_inprog(branch& myobj) {
{ string context("->"); // for showing errors
string context("->");// for showing errors int count_symbols = 0;
int count_symbols = 0; bool prog_found = false;
bool prog_found = false;
if (myobj.arg1 == -1) if (myobj.arg1 == -1) {
{ ERR_CONTEXT(ret_unknown_err);
ERR_CONTEXT(ret_unknown_err); return -1;
return -1; }
// syntax must be
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
// find next oprogram object
for (unsigned int i = myobj.arg1 + 1; i < size(); i++) {
// count symbol
if (seq_type(i) == cmd_symbol) count_symbols++;
// stop if prog
else if (seq_type(i) == cmd_program) {
prog_found = true;
break;
} }
// found something other than symbol
// syntax must be else {
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram> ERR_CONTEXT(ret_bad_operand_type);
show_error(_err, context);
// find next oprogram object return -1;
for (unsigned int i = myobj.arg1 + 1; i < size(); i++)
{
// count symbol
if (seq_type(i) == cmd_symbol)
count_symbols++;
// stop if prog
else if (seq_type(i) == cmd_program)
{
prog_found = true;
break;
}
// found something other than symbol
else
{
ERR_CONTEXT(ret_bad_operand_type);
show_error(_err, context);
return -1;
}
} }
}
// found 0 symbols // found 0 symbols
if (count_symbols == 0) if (count_symbols == 0) {
{ ERR_CONTEXT(ret_syntax);
ERR_CONTEXT(ret_syntax); show_error(_err, context);
show_error(_err, context); return -1;
return -1; }
}
// <oprogram> is missing // <oprogram> is missing
if (! prog_found) if (!prog_found) {
{ ERR_CONTEXT(ret_syntax);
ERR_CONTEXT(ret_syntax); show_error(_err, context);
show_error(_err, context); return -1;
return -1; }
}
// check symbols number vs stack size // check symbols number vs stack size
if (stack_size() < count_symbols) if (stack_size() < count_symbols) {
{ ERR_CONTEXT(ret_missing_operand);
ERR_CONTEXT(ret_missing_operand); show_error(_err, context);
show_error(_err, context); return -1;
return -1; }
}
// load variables // load variables
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) {
{ _local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0),
_local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0)); _stack->get_len(0));
(void)_stack->pop_back(); (void)_stack->pop_back();
} }
// run the program // run the program
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value); string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
program prog(this); program prog(this);
// make the program from entry // make the program from entry
if (program::parse(entry.c_str(), prog) == ret_ok) if (program::parse(entry.c_str(), prog) == ret_ok) {
{ // run it
// run it prog.run(*_stack, *_heap);
prog.run(*_stack, *_heap); }
}
// point on next command // point on next command
return myobj.arg1 + count_symbols + 2; return myobj.arg1 + count_symbols + 2;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,155 +1,140 @@
// //
void rpn_swap(void) void rpn_swap(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack); (void)_stack->pop_back(2);
(void)_stack->pop_back(2); stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack); stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack); _calc_stack.pop_back(2);
_calc_stack.pop_back(2);
} }
void rpn_drop(void) void rpn_drop(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); (void)_stack->pop_back();
}
void rpn_drop2(void) {
MIN_ARGUMENTS(2);
(void)_stack->pop_back(2);
}
void rpn_dropn(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args + 1);
(void)_stack->pop_back(args + 1);
}
void rpn_erase(void) { (void)_stack->pop_back(_stack->size()); }
void rpn_dup(void) {
MIN_ARGUMENTS(1);
stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack);
}
void rpn_dup2(void) {
MIN_ARGUMENTS(2);
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
}
void rpn_dupn(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args + 1);
_stack->pop_back();
for (int i = 0; i < args; i++)
stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack);
}
void rpn_pick(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
unsigned int to_pick =
(unsigned int)int(((number*)_stack->pop_back())->_value);
// treat stack depth errors
if ((to_pick == 0) || (to_pick > _stack->size())) {
ERR_CONTEXT(ret_out_of_range);
return;
}
stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack);
}
void rpn_rot(void) {
MIN_ARGUMENTS(3);
stack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
(void)_stack->pop_back(3);
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack);
_calc_stack.pop_back(3);
}
void rpn_depth(void) {
unsigned long depth = (unsigned long)_stack->size();
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
num->set(depth);
}
void rpn_roll(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args + 1);
_stack->pop_back();
for (int i = 0; i < args; i++) {
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
(void)_stack->pop_back(); (void)_stack->pop_back();
}
for (int i = 1; i < args; i++)
stack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack);
stack::copy_and_push_back(_calc_stack, args - 1, *_stack);
_calc_stack.pop_back(args);
} }
void rpn_drop2(void) void rpn_rolld(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number);
(void)_stack->pop_back(2);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args + 1);
_stack->pop_back();
for (int i = 0; i < args; i++) {
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
(void)_stack->pop_back();
}
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack);
for (int i = 1; i < args; i++)
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack);
_calc_stack.pop_back(args);
} }
void rpn_dropn(void) void rpn_over(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd); stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
MIN_ARGUMENTS(args+1);
(void)_stack->pop_back(args+1);
}
void rpn_erase(void)
{
(void)_stack->pop_back(_stack->size());
}
void rpn_dup(void)
{
MIN_ARGUMENTS(1);
stack::copy_and_push_back(*_stack, _stack->size()-1, *_stack);
}
void rpn_dup2(void)
{
MIN_ARGUMENTS(2);
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
}
void rpn_dupn(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args+1);
_stack->pop_back();
for (int i=0;i<args;i++)
stack::copy_and_push_back(*_stack, _stack->size()-args, *_stack);
}
void rpn_pick(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_back())->_value);
// treat stack depth errors
if ((to_pick == 0) || (to_pick > _stack->size()))
{
ERR_CONTEXT(ret_out_of_range);
return;
}
stack::copy_and_push_back(*_stack, _stack->size()-to_pick, *_stack);
}
void rpn_rot(void)
{
MIN_ARGUMENTS(3);
stack::copy_and_push_back(*_stack, _stack->size()-3, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
(void)_stack->pop_back(3);
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-3, *_stack);
_calc_stack.pop_back(3);
}
void rpn_depth(void)
{
unsigned long depth = (unsigned long)_stack->size();
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
num->set(depth);
}
void rpn_roll(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args+1);
_stack->pop_back();
for(int i=0;i<args;i++)
{
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
(void)_stack->pop_back();
}
for(int i=1;i<args;i++)
stack::copy_and_push_back(_calc_stack, args-1-i, *_stack);
stack::copy_and_push_back(_calc_stack, args-1, *_stack);
_calc_stack.pop_back(args);
}
void rpn_rolld(void)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
MIN_ARGUMENTS(args+1);
_stack->pop_back();
for(int i=0;i<args;i++)
{
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
(void)_stack->pop_back();
}
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-args, *_stack);
for(int i=1;i<args;i++)
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-i, *_stack);
_calc_stack.pop_back(args);
}
void rpn_over(void)
{
MIN_ARGUMENTS(2);
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
} }

View file

@ -1,327 +1,273 @@
// //
void rpn_sto(void) void rpn_sto(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
string name(((symbol*)_stack->pop_back())->_value); string name(((symbol*)_stack->pop_back())->_value);
_heap->add(name, _stack->get_obj(0), _stack->get_len(0)); _heap->add(name, _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back(); (void)_stack->pop_back();
} }
// //
void rpn_stoadd(void) void rpn_stoadd(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
{ // get variable value on stack level 1, make op then modify variable
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_plus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
{
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
rpn_plus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stosub(void)
{
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
{
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_minus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
{
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
rpn_minus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stomul(void)
{
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
{
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_mul();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
{
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
rpn_mul();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stodiv(void)
{
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
{
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_div();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
{
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
rpn_div();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stoneg(void)
{
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_symbol)
{
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_neg();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stoinv(void)
{
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_symbol)
{
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok)
{
rpn_inv();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_rcl(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
// recall a variable
object* obj;
unsigned int size;
string variable(((symbol*)_stack->back())->_value); string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
// mind the order of heaps if (_err == ret_ok) {
if (find_variable(variable, obj, size)) rpn_plus();
{ _heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back(); _stack->pop_back();
stack::copy_and_push_back(obj, *_stack, size);
} }
else } else if (_stack->get_type(1) == cmd_symbol &&
ERR_CONTEXT(ret_unknown_variable); _stack->get_type(0) == cmd_number) {
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
rpn_plus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_edit(void) void rpn_stosub(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(1);
FILE* tmp = tmpfile(); if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
if (tmp != NULL) // get variable value on stack level 1, make op then modify variable
{ string variable(((symbol*)_stack->back())->_value);
// re-write stack objet in a stream rpn_rcl();
((object*)_stack->pop_back())->show(tmp); if (_err == ret_ok) {
rpn_minus();
// edit: stuff chars using readline facility _heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
int len = (int)ftell(tmp); _stack->pop_back();
rewind(tmp);
// get stream data
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
if (file_data != MAP_FAILED)
{
// set it as the linenoise line entry
linenoisePreloadBuffer((const char*)file_data);
munmap(file_data, len);
}
else
ERR_CONTEXT(ret_runtime_error);
fclose(tmp);
} }
else } else if (_stack->get_type(1) == cmd_symbol &&
ERR_CONTEXT(ret_runtime_error); _stack->get_type(0) == cmd_number) {
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
rpn_minus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stomul(void) {
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
rpn_mul();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else if (_stack->get_type(1) == cmd_symbol &&
_stack->get_type(0) == cmd_number) {
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
rpn_mul();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stodiv(void) {
MIN_ARGUMENTS(2);
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
rpn_div();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else if (_stack->get_type(1) == cmd_symbol &&
_stack->get_type(0) == cmd_number) {
// copy value, get variable value on stack level 1,
// put back value on stack level 1, make op then modify variable
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back();
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
rpn_div();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stoneg(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_symbol) {
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
rpn_neg();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_stoinv(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_symbol) {
// get variable value on stack level 1, make op then modify variable
string variable(((symbol*)_stack->back())->_value);
rpn_rcl();
if (_err == ret_ok) {
rpn_inv();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_rcl(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
// recall a variable
object* obj;
unsigned int size;
string variable(((symbol*)_stack->back())->_value);
// mind the order of heaps
if (find_variable(variable, obj, size)) {
(void)_stack->pop_back();
stack::copy_and_push_back(obj, *_stack, size);
} else
ERR_CONTEXT(ret_unknown_variable);
}
void rpn_edit(void) {
MIN_ARGUMENTS(1);
FILE* tmp = tmpfile();
if (tmp != NULL) {
// re-write stack objet in a stream
((object*)_stack->pop_back())->show(tmp);
// edit: stuff chars using readline facility
int len = (int)ftell(tmp);
rewind(tmp);
// get stream data
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
if (file_data != MAP_FAILED) {
// set it as the linenoise line entry
linenoisePreloadBuffer((const char*)file_data);
munmap(file_data, len);
} else
ERR_CONTEXT(ret_runtime_error);
fclose(tmp);
} else
ERR_CONTEXT(ret_runtime_error);
} }
// carefull : this is not a langage command // carefull : this is not a langage command
void auto_rcl(symbol* symb) void auto_rcl(symbol* symb) {
{ if (symb->_auto_eval) {
if (symb->_auto_eval)
{
object* obj;
unsigned int size;
string variable(symb->_value);
// mind the order of heaps
if (find_variable(variable, obj, size))
{
stack::copy_and_push_back(obj, *_stack, size);
if (obj->_type == cmd_program)
rpn_eval();
}
else
stack::copy_and_push_back(symb, *_stack, symb->size());
}
else
stack::copy_and_push_back(symb, *_stack, symb->size());
}
void rpn_purge(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
string name(((symbol*)_stack->pop_back())->_value);
if (!_heap->erase(name))
ERR_CONTEXT(ret_unknown_variable);
}
void rpn_vars(void)
{
object* obj; object* obj;
unsigned int size; unsigned int size;
program* parent = _parent_prog; string variable(symb->_value);
string name;
// heap variables // mind the order of heaps
for (int i=0; i<(int)_heap->count_vars(); i++) if (find_variable(variable, obj, size)) {
{ stack::copy_and_push_back(obj, *_stack, size);
(void)_heap->get_by_index(i, name, obj, size); if (obj->_type == cmd_program) rpn_eval();
printf("var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]); } else
obj->show(); stack::copy_and_push_back(symb, *_stack, symb->size());
printf("\n"); } else
} stack::copy_and_push_back(symb, *_stack, symb->size());
// parents local variables
while (parent != NULL)
{
for (int i=0; i<(int)parent->_local_heap.size(); i++)
{
(void)parent->_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
parent = parent->_parent_prog;
}
// local variables
for (int i=0; i<(int)_local_heap.size(); i++)
{
(void)_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
} }
void rpn_clusr(void) void rpn_purge(void) {
{ MIN_ARGUMENTS(1);
_heap->erase_all(); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
string name(((symbol*)_stack->pop_back())->_value);
if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable);
} }
void rpn_vars(void) {
object* obj;
unsigned int size;
program* parent = _parent_prog;
string name;
// heap variables
for (int i = 0; i < (int)_heap->count_vars(); i++) {
(void)_heap->get_by_index(i, name, obj, size);
printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(),
object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
// parents local variables
while (parent != NULL) {
for (int i = 0; i < (int)parent->_local_heap.size(); i++) {
(void)parent->_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
parent = parent->_parent_prog;
}
// local variables
for (int i = 0; i < (int)_local_heap.size(); i++) {
(void)_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
}
void rpn_clusr(void) { _heap->erase_all(); }

View file

@ -1,152 +1,140 @@
void rpn_instr() void rpn_instr() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
// stringify only if not already a string // stringify only if not already a string
if (_stack->get_type(0) != cmd_string) if (_stack->get_type(0) != cmd_string) {
{ // write the object in stack(0) in a string and remove this obj
// write the object in stack(0) in a string and remove this obj FILE* tmp = tmpfile();
FILE* tmp = tmpfile(); if (tmp != NULL) {
if (tmp != NULL) ((object*)_stack->pop_back())->show(tmp);
{
((object*)_stack->pop_back())->show(tmp);
// reserve the correct size on stack // reserve the correct size on stack
unsigned int str_size = (unsigned int)ftell(tmp); unsigned int str_size = (unsigned int)ftell(tmp);
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string); ostring* str = (ostring*)_stack->allocate_back(
str->_len = str_size; str_size + 1 + sizeof(ostring), cmd_string);
str->_len = str_size;
// fill the obj // fill the obj
rewind(tmp); rewind(tmp);
if (fread(str->_value, str_size, 1, tmp) != 1) if (fread(str->_value, str_size, 1, tmp) != 1)
ERR_CONTEXT(ret_runtime_error); ERR_CONTEXT(ret_runtime_error);
str->_value[str_size] = 0; str->_value[str_size] = 0;
fclose(tmp); fclose(tmp);
} } else
else ERR_CONTEXT(ret_runtime_error);
ERR_CONTEXT(ret_runtime_error); }
}
} }
void rpn_strout() void rpn_strout() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
string entry(((ostring*)_stack->pop_back())->_value); string entry(((ostring*)_stack->pop_back())->_value);
program prog; program prog;
// make program from string in stack level 1 // make program from string in stack level 1
if (program::parse(entry.c_str(), prog) == ret_ok) if (program::parse(entry.c_str(), prog) == ret_ok)
// run it // run it
prog.run(*_stack, *_heap); prog.run(*_stack, *_heap);
} }
void rpn_chr() void rpn_chr() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// get arg as number % 256 // get arg as number % 256
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr,
if (the_chr<32 || the_chr>126) floating_t::s_mpfr_rnd);
the_chr = '.'; if (the_chr < 32 || the_chr > 126) the_chr = '.';
// reserve the correct size on stack (1 char) // reserve the correct size on stack (1 char)
unsigned int str_size = 1; unsigned int str_size = 1;
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string); ostring* str = (ostring*)_stack->allocate_back(str_size + 1 + sizeof(ostring),
cmd_string);
str->_len = str_size;
str->_value[0] = the_chr;
str->_value[1] = 0;
}
void rpn_num() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0];
number* numb =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
numb->_value = the_chr;
}
void rpn_strsize() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
double len = ((ostring*)_stack->pop_back())->_len;
number* numb =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
numb->_value = len;
}
void rpn_strpos() {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
ARG_MUST_BE_OF_TYPE(1, cmd_string);
long pos = 0;
char* src = ((ostring*)_stack->get_obj(1))->_value;
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
if (found != NULL) pos = (long)(found - src) + 1L;
_stack->pop_back(2);
number* numb =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
numb->_value = pos;
}
void rpn_strsub() {
MIN_ARGUMENTS(3);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
ARG_MUST_BE_OF_TYPE(2, cmd_string);
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
long len = ((ostring*)_stack->get_obj(2))->_len;
bool result_is_void = false;
_stack->pop_back(2);
if (first < 0) first = 0;
if (last < 0) last = 0;
if (first > len && last > len)
result_is_void = true;
else {
if (first > len) first = len - 1;
if (last > len) last = len - 1;
if (first > last) result_is_void = true;
}
if (!result_is_void) {
unsigned int str_size = last - first + 1;
ostring* str = (ostring*)_calc_stack.allocate_back(
str_size + 1 + sizeof(ostring), cmd_string);
str->_len = str_size; str->_len = str_size;
str->_value[0] = the_chr;
str->_value[1] = 0; memcpy(((ostring*)_calc_stack.back())->_value,
} ((ostring*)_stack->get_obj(0))->_value + first, str_size);
((ostring*)_calc_stack.back())->_value[str_size] = 0;
void rpn_num()
{ _stack->pop_back();
MIN_ARGUMENTS(1); stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
ARG_MUST_BE_OF_TYPE(0, cmd_string); _calc_stack.pop_back();
} else {
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0]; _stack->pop_back();
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number); ostring* str =
numb->_value = the_chr; (ostring*)_stack->allocate_back(1 + sizeof(ostring), cmd_string);
} str->_len = 0;
str->_value[0] = 0;
void rpn_strsize() }
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
double len = ((ostring*)_stack->pop_back())->_len;
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
numb->_value = len;
}
void rpn_strpos()
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
ARG_MUST_BE_OF_TYPE(1, cmd_string);
long pos = 0;
char* src = ((ostring*)_stack->get_obj(1))->_value;
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
if (found != NULL)
pos = (long)(found - src)+1L;
_stack->pop_back(2);
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
numb->_value = pos;
}
void rpn_strsub()
{
MIN_ARGUMENTS(3);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
ARG_MUST_BE_OF_TYPE(2, cmd_string);
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
long len = ((ostring*)_stack->get_obj(2))->_len;
bool result_is_void = false;
_stack->pop_back(2);
if (first < 0)
first = 0;
if (last < 0)
last = 0;
if (first > len && last > len)
result_is_void=true;
else
{
if (first > len)
first = len -1;
if (last > len)
last = len -1;
if (first > last)
result_is_void=true;
}
if (!result_is_void)
{
unsigned int str_size = last - first + 1;
ostring* str = (ostring*)_calc_stack.allocate_back(str_size+1+sizeof(ostring), cmd_string);
str->_len = str_size;
memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->get_obj(0))->_value+first, str_size);
((ostring*)_calc_stack.back())->_value[str_size] = 0;
_stack->pop_back();
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
_calc_stack.pop_back();
}
else
{
_stack->pop_back();
ostring* str = (ostring*)_stack->allocate_back(1+sizeof(ostring), cmd_string);
str->_len = 0;
str->_value[0] = 0;
}
} }

View file

@ -1,251 +1,223 @@
void test_get_stack(string& stack_is, stack& stk) void test_get_stack(string& stack_is, stack& stk) {
{ // write stack in a string, each entry separated between commas
// write stack in a string, each entry separated between commas for (int i = 0; i < (int)stk.size(); i++) {
for (int i = 0; i < (int)stk.size(); i++) FILE* tmp_file = tmpfile();
{ char* line = NULL;
FILE* tmp_file = tmpfile(); size_t len;
char* line = NULL;
size_t len;
if (i > 0) if (i > 0) stack_is += ", ";
stack_is += ", ";
if (tmp_file != NULL) if (tmp_file != NULL) {
{ ((object*)stk.seq_obj(i))->show(tmp_file);
((object*)stk.seq_obj(i))->show(tmp_file);
// write stack in a tmp file // write stack in a tmp file
(void)rewind(tmp_file); (void)rewind(tmp_file);
if (getline(&line, &len, tmp_file) >=0) if (getline(&line, &len, tmp_file) >= 0) {
{ stack_is += line;
stack_is += line; free(line);
free(line); }
} (void)fclose(tmp_file);
(void)fclose(tmp_file); } else
} ERR_CONTEXT(ret_runtime_error);
else }
ERR_CONTEXT(ret_runtime_error);
}
} }
void test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) void test_show_result(string title, int tests, int tests_failed, int steps,
{ int steps_failed) {
printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests-tests_failed); printf("%s: run %d tests: %d passed, ", title.c_str(), tests,
if(tests_failed>0) tests - tests_failed);
printf(FG_RED); if (tests_failed > 0) printf(FG_RED);
printf("%d failed", tests_failed); printf("%d failed", tests_failed);
if(tests_failed>0) if (tests_failed > 0) printf(COLOR_OFF);
printf(COLOR_OFF);
printf(" (%d steps: %d passed, ", steps, steps-steps_failed); printf(" (%d steps: %d passed, ", steps, steps - steps_failed);
if(steps_failed>0) if (steps_failed > 0) printf(FG_RED);
printf(FG_RED); printf("%d failed", steps_failed);
printf("%d failed", steps_failed); if (steps_failed > 0) printf(COLOR_OFF);
if(steps_failed>0) printf(")\n");
printf(COLOR_OFF);
printf(")\n");
} }
void rpn_test() void rpn_test() {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
int total_tests=0; int total_tests = 0;
int total_tests_failed=0; int total_tests_failed = 0;
int total_steps=0; int total_steps = 0;
int total_steps_failed=0; int total_steps_failed = 0;
string test_filename = ((ostring*)_stack->pop_back())->_value; string test_filename = ((ostring*)_stack->pop_back())->_value;
printf("\nrpn version is %s\n", version); printf("\nrpn version is %s\n", version);
test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); test(test_filename, total_tests, total_tests_failed, total_steps,
test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); total_steps_failed);
test_show_result("Total", total_tests, total_tests_failed, total_steps,
total_steps_failed);
} }
void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed) void test(string test_filename, int& total_tests, int& total_tests_failed,
{ int& total_steps, int& total_steps_failed) {
const string stack_size("-> stack size should be "); const string stack_size("-> stack size should be ");
const string stack_value("-> stack should be "); const string stack_value("-> stack should be ");
const string cmd_error("-> error should be "); const string cmd_error("-> error should be ");
const string cmd_exit("exit test"); const string cmd_exit("exit test");
ifstream test_file(test_filename.c_str()); ifstream test_file(test_filename.c_str());
int tests = 0; int tests = 0;
int tests_failed = 0; int tests_failed = 0;
int steps = 0; int steps = 0;
int steps_failed = 0; int steps_failed = 0;
if (test_file.is_open()) if (test_file.is_open()) {
{ string test_title;
string test_title; string entry;
string entry; ret_value ret;
ret_value ret; stack stk;
stack stk; heap hp;
heap hp; bool failed = false;
bool failed = false; bool is_first_step;
bool is_first_step; bool is_test_error_shown;
bool is_test_error_shown; int last_err;
int last_err; stringstream cerr_buffer;
stringstream cerr_buffer; streambuf* cerr_old_buffer;
streambuf* cerr_old_buffer;
// redirect cerr // redirect cerr
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf()); cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
while (!test_file.eof()) while (!test_file.eof()) {
{ getline(test_file, entry);
getline(test_file, entry);
if (entry.substr(0,8)=="#include") if (entry.substr(0, 8) == "#include")
test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed); test(entry.substr(9), total_tests, total_tests_failed, total_steps,
else if (entry.substr(0,2)=="##") total_steps_failed);
printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str()); else if (entry.substr(0, 2) == "##")
else if (entry.substr(0,2)=="# ") printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str());
{ else if (entry.substr(0, 2) == "# ") {
// indicates the status of previous test
if (failed == false && tests > 0)
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
failed = false;
// read a test title
test_title = entry;
is_first_step = true;
is_test_error_shown = false;
printf("%s", test_title.c_str());
}
// treat "-> stack size should be "
else if (entry.find(stack_size, 0) == 0)
{
// count test and step
if (is_first_step)
tests++;
steps++;
// check current stack size
istringstream isub;
int size;
isub.str(entry.substr(stack_size.size()));
isub>>size;
if (size != (int)stk.size())
{
// count fail test and step
if (!is_test_error_shown)
{
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n", stk.size());
failed = true;
}
is_first_step = false;
}
// treat "-> stack should be "
else if (entry.find(stack_value, 0) == 0)
{
// count test
if (is_first_step)
tests++;
steps++;
// check current stack value
string stack_should_be = entry.substr(stack_value.size());
string stack_is;
test_get_stack(stack_is, stk);
if (stack_is != stack_should_be)
{
// count fail test and step
if (!is_test_error_shown)
{
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n", stack_is.c_str());
failed = true;
}
is_first_step = false;
}
// treat "-> error should be "
else if (entry.find(cmd_error, 0) == 0)
{
// count test
if (is_first_step)
tests++;
steps++;
// check current error
istringstream isub;
int err_should_be;
isub.str(entry.substr(cmd_error.size()));
isub>>err_should_be;
if (err_should_be != last_err)
{
// count fail test and step
if (!is_test_error_shown)
{
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
failed = true;
}
is_first_step = false;
}
else if (entry.find(cmd_exit, 0) == 0)
{
// forced test end
break;
}
else if (entry.size() > 0)
{
// parse entry and run line
program prog;
ret = program::parse(entry.c_str(), prog);
if (ret == ret_ok)
{
// run it
(void)prog.run(stk, hp);
last_err = (int)prog.get_err();
}
}
}
// last test
// indicates the status of previous test // indicates the status of previous test
if (failed == false && tests > 0) if (failed == false && tests > 0)
printf(FG_GREEN " PASSED" COLOR_OFF "\n"); printf(FG_GREEN " PASSED" COLOR_OFF "\n");
failed = false;
// cerr back // read a test title
cerr.rdbuf(cerr_old_buffer); test_title = entry;
is_first_step = true;
is_test_error_shown = false;
printf("%s", test_title.c_str());
}
// treat "-> stack size should be "
else if (entry.find(stack_size, 0) == 0) {
// count test and step
if (is_first_step) tests++;
steps++;
// conclusion: show and keep for total // check current stack size
if (tests != 0) istringstream isub;
{ int size;
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
total_tests += tests; isub.str(entry.substr(stack_size.size()));
total_tests_failed += tests_failed; isub >> size;
total_steps += steps; if (size != (int)stk.size()) {
total_steps_failed += steps_failed; // count fail test and step
if (!is_test_error_shown) {
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n",
stk.size());
failed = true;
} }
is_first_step = false;
}
// treat "-> stack should be "
else if (entry.find(stack_value, 0) == 0) {
// count test
if (is_first_step) tests++;
steps++;
// check current stack value
string stack_should_be = entry.substr(stack_value.size());
string stack_is;
test_get_stack(stack_is, stk);
if (stack_is != stack_should_be) {
// count fail test and step
if (!is_test_error_shown) {
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n",
stack_is.c_str());
failed = true;
}
is_first_step = false;
}
// treat "-> error should be "
else if (entry.find(cmd_error, 0) == 0) {
// count test
if (is_first_step) tests++;
steps++;
// check current error
istringstream isub;
int err_should_be;
isub.str(entry.substr(cmd_error.size()));
isub >> err_should_be;
if (err_should_be != last_err) {
// count fail test and step
if (!is_test_error_shown) {
printf(FG_RED " FAIL" COLOR_OFF "\n");
tests_failed++;
is_test_error_shown = true;
}
steps_failed++;
// show failure
printf("\t%s\n", entry.c_str());
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
failed = true;
}
is_first_step = false;
} else if (entry.find(cmd_exit, 0) == 0) {
// forced test end
break;
} else if (entry.size() > 0) {
// parse entry and run line
program prog;
ret = program::parse(entry.c_str(), prog);
if (ret == ret_ok) {
// run it
(void)prog.run(stk, hp);
last_err = (int)prog.get_err();
}
}
} }
else
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str()); // last test
// indicates the status of previous test
if (failed == false && tests > 0) printf(FG_GREEN " PASSED" COLOR_OFF "\n");
// cerr back
cerr.rdbuf(cerr_old_buffer);
// conclusion: show and keep for total
if (tests != 0) {
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
total_tests += tests;
total_tests_failed += tests_failed;
total_steps += steps;
total_steps_failed += steps_failed;
}
} else
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str());
} }

View file

@ -1,270 +1,251 @@
int cmp_strings_on_stack_top() int cmp_strings_on_stack_top() {
{ // _stack sould have 2 strings at level 1 and 2
// _stack sould have 2 strings at level 1 and 2 // this function removes these 2 entries
// this function removes these 2 entries ostring* right = (ostring*)_stack->pop_back();
ostring* right = (ostring*)_stack->pop_back(); ostring* left = (ostring*)_stack->pop_back();
ostring* left = (ostring*)_stack->pop_back(); return strncmp(left->_value, right->_value, min(left->_len, right->_len));
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
} }
void rpn_sup(void) void rpn_sup(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2);
// numbers // numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
{ number* right = (number*)_stack->pop_back();
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp > 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_sup_eq(void)
{
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
{
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp >= 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_inf(void)
{
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
{
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp < 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_inf_eq(void)
{
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
{
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp <= 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_diff(void)
{
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
{
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// complexes
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
{
bool diff = false;
complex* right = (complex*)_stack->pop_back();
complex* left = (complex*)_stack->pop_back();
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
diff = true;
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
if (diff)
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp != 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_eq(void)
{
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
{
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// complexes
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
{
bool diff = false;
complex* right = (complex*)_stack->pop_back();
complex* left = (complex*)_stack->pop_back();
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
diff = true;
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
if (diff)
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
else
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
{
int res_cmp = cmp_strings_on_stack_top();
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp == 0) ? 1L : 0L;
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_test_and(void)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back(); number* left = (number*)_stack->back();
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
&& (mpfr_cmp_si(right->_value.mpfr, 0) != 0)) mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string &&
_stack->get_type(1) == cmd_string) {
int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp > 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_test_or(void) void rpn_sup_eq(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back(); // numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back(); number* left = (number*)_stack->back();
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
|| (mpfr_cmp_si(right->_value.mpfr, 0) != 0)) mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string &&
_stack->get_type(1) == cmd_string) {
int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp >= 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_test_xor(void) void rpn_inf(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back(); // numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back(); number* left = (number*)_stack->back();
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0) if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
{ mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
else else
{ mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0) }
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); // strings
else else if (_stack->get_type(0) == cmd_string &&
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); _stack->get_type(1) == cmd_string) {
} int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp < 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_test_not(void) void rpn_inf_eq(void) {
{ MIN_ARGUMENTS(2);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back(); number* left = (number*)_stack->back();
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string &&
_stack->get_type(1) == cmd_string) {
int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp <= 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_same(void) void rpn_diff(void) {
{ MIN_ARGUMENTS(2);
rpn_eq();
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// complexes
else if (_stack->get_type(0) == cmd_complex &&
_stack->get_type(1) == cmd_complex) {
bool diff = false;
complex* right = (complex*)_stack->pop_back();
complex* left = (complex*)_stack->pop_back();
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
diff = true;
number* num =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
if (diff)
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string &&
_stack->get_type(1) == cmd_string) {
int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp != 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_eq(void) {
MIN_ARGUMENTS(2);
// numbers
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
// complexes
else if (_stack->get_type(0) == cmd_complex &&
_stack->get_type(1) == cmd_complex) {
bool diff = false;
complex* right = (complex*)_stack->pop_back();
complex* left = (complex*)_stack->pop_back();
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
diff = true;
number* num =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
if (diff)
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
else
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
}
// strings
else if (_stack->get_type(0) == cmd_string &&
_stack->get_type(1) == cmd_string) {
int res_cmp = cmp_strings_on_stack_top();
number* res =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
res->_value = (res_cmp == 0) ? 1L : 0L;
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_test_and(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) &&
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void rpn_test_or(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) ||
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void rpn_test_xor(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0) {
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
} else {
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
}
void rpn_test_not(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->back();
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void rpn_same(void) { rpn_eq(); }

View file

@ -1,263 +1,239 @@
// //
void rpn_pi(void) void rpn_pi(void) {
{ number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number); CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
} }
void rpn_d2r(void) void rpn_d2r(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// add pi on stack // add pi on stack
rpn_pi(); rpn_pi();
floating_t* pi = &((number*)_stack->pop_back())->_value; floating_t* pi = &((number*)_stack->pop_back())->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(
mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
}
void rpn_r2d(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// add pi on stack
rpn_pi();
floating_t* pi = &((number*)_stack->pop_back())->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(
mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
}
void rpn_sin(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value; floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd)); // sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
floating_t* tmp =
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
->_value;
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_r2d(void) void rpn_asin(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// add pi on stack if (_stack->get_type(0) == cmd_number) {
rpn_pi();
floating_t* pi = &((number*)_stack->pop_back())->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd)); number* num;
complex* i;
// asin(z)=-iln(iz+sqrt(1-z*z))
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
i = (complex*)_calc_stack.get_obj(0);
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_dup();
rpn_square();
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();
rpn_neg();
rpn_squareroot();
rpn_swap();
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
rpn_plus();
rpn_ln();
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
rpn_neg();
_calc_stack.pop_back();
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_sin(void) void rpn_cos(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
{
// sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* tmp =
floating_t* im = ((complex*)_stack->get_obj(0))->im(); &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
->_value;
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); floating_t* re = ((complex*)_stack->get_obj(0))->re();
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2); CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
} CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
else CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
ERR_CONTEXT(ret_bad_operand_type);
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_asin(void) void rpn_acos(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // acos(z)=pi/2-asin(z)
else if (_stack->get_type(0) == cmd_complex) rpn_asin();
{ rpn_pi();
number* num; number* num =
complex* i; (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
//asin(z)=-iln(iz+sqrt(1-z*z)) rpn_div();
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); rpn_minus();
rpn_neg();
i = (complex*)_calc_stack.get_obj(0); } else
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd)); ERR_CONTEXT(ret_bad_operand_type);
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_dup();
rpn_square();
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();
rpn_neg();
rpn_squareroot();
rpn_swap();
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
rpn_plus();
rpn_ln();
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
rpn_neg();
_calc_stack.pop_back();
}
else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_cos(void) void rpn_tan(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} // tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
{
// cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re(); floating_t* tmp =
floating_t* im = ((complex*)_stack->get_obj(0))->im(); &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
->_value;
CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); floating_t* re = ((complex*)_stack->get_obj(0))->re();
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); floating_t* im = ((complex*)_stack->get_obj(0))->im();
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2); // x->2x
} CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
else // y->2y
ERR_CONTEXT(ret_bad_operand_type); CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
// sin(2x)+sinh(2y)
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
// cosh(2y)+cos(2x)
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
// sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
} else
ERR_CONTEXT(ret_bad_operand_type);
} }
void rpn_acos(void) void rpn_atan(void) {
{ MIN_ARGUMENTS(1);
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number) if (_stack->get_type(0) == cmd_number) {
{ floating_t* left = &((number*)_stack->get_obj(0))->_value;
floating_t* left = &((number*)_stack->get_obj(0))->_value; CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); } else if (_stack->get_type(0) == cmd_complex) {
} number* num;
else if (_stack->get_type(0) == cmd_complex) complex* i;
{
//acos(z)=pi/2-asin(z) // atan(z)=0.5i(ln((1-iz)/(1+iz))
rpn_asin(); stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
rpn_pi();
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); i = (complex*)_calc_stack.get_obj(0);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
rpn_div(); CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();
rpn_neg(); stack::copy_and_push_back(_calc_stack, 0, *_stack);
} rpn_mul();
else num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
ERR_CONTEXT(ret_bad_operand_type); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
} rpn_minus(); // iz-1
rpn_neg(); // 1-iz
void rpn_tan(void) rpn_dup();
{ rpn_neg(); // iz-1
MIN_ARGUMENTS(1); num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
if (_stack->get_type(0) == cmd_number) rpn_plus(); // iz+1
{ rpn_div();
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); rpn_ln();
} CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
else if (_stack->get_type(0) == cmd_complex) stack::copy_and_push_back(_calc_stack, 0, *_stack);
{ rpn_mul();
// tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); _calc_stack.pop_back();
} else
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; ERR_CONTEXT(ret_bad_operand_type);
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
//x->2x
CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
//y->2y
CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
//sin(2x)+sinh(2y)
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
//cosh(2y)+cos(2x)
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
//sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_atan(void)
{
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
else if (_stack->get_type(0) == cmd_complex)
{
number* num;
complex* i;
//atan(z)=0.5i(ln((1-iz)/(1+iz))
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
i = (complex*)_calc_stack.get_obj(0);
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();//iz-1
rpn_neg();//1-iz
rpn_dup();
rpn_neg();//iz-1
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_plus();//iz+1
rpn_div();
rpn_ln();
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
stack::copy_and_push_back(_calc_stack, 0, *_stack);
rpn_mul();
_calc_stack.pop_back();
}
else
ERR_CONTEXT(ret_bad_operand_type);
} }

View file

@ -6,326 +6,281 @@
using namespace std; using namespace std;
// allocation base size // allocation base size
#define ALLOC_STACK_CHUNK (64*1024) #define ALLOC_STACK_CHUNK (64 * 1024)
// //
class stack class stack {
{ public:
public: stack() {
stack() _base = NULL;
{ _base_pointer = NULL;
_base = NULL; _total_size = 0;
_base_pointer = NULL; _total_count_pointer = 0;
_total_size = 0; erase();
_total_count_pointer = 0; }
erase();
virtual ~stack() {
if (_base != NULL) free(_base);
if (_base_pointer != NULL) free(_base_pointer);
}
void erase() {
_current = _base;
_count = 0;
}
//
static void copy_and_push_back(stack& from, unsigned int index_from,
stack& to) {
// copy a whole stack entry and push it back to another stack
object* allocated =
to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
if (allocated->_type == cmd_number)
((number*)allocated)->move();
else if (allocated->_type == cmd_complex)
((complex*)allocated)->move();
}
//
static void copy_and_push_back(object* from, stack& to, unsigned int size) {
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(size, from->_type);
memcpy(allocated, from, size);
if (allocated->_type == cmd_number)
((number*)allocated)->move();
else if (allocated->_type == cmd_complex)
((complex*)allocated)->move();
}
object* allocate_back(unsigned int size, cmd_type_t type) {
object* allocated;
bool data_is_reallocated = false;
char* old_base;
// manage data memory allocation (add as much as memory it is needed)
if (((_current - _base) + size) > _total_size) {
// calc nb of needed pages
unsigned long page_number =
1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
_total_size += page_number * ALLOC_STACK_CHUNK;
old_base = _base;
_base = (char*)realloc(_base, _total_size);
_current = _base + (_current - old_base);
data_is_reallocated = true;
} }
virtual ~stack() // manage pointers memory allocation (add one page if needed)
{ if ((_count + 1) > _total_count_pointer) {
if (_base != NULL) _base_pointer = (object**)realloc(
free(_base); _base_pointer,
if (_base_pointer != NULL) (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
free(_base_pointer); _total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
} }
void erase() // recalc object pointers in case of base reallocation
{ if (data_is_reallocated) {
_current = _base; for (int i = 0; i < _count; i++) {
_count = 0; _base_pointer[i] =
(object*)(_base + ((char*)_base_pointer[i] - old_base));
if (_base_pointer[i]->_type == cmd_number)
((number*)_base_pointer[i])->move();
else if (_base_pointer[i]->_type == cmd_complex)
((complex*)_base_pointer[i])->move();
}
} }
// // manage stack itself
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to) _base_pointer[_count++] = (object*)_current;
{ allocated = (object*)_current;
// copy a whole stack entry and push it back to another stack _current += size;
object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
if (allocated->_type == cmd_number) // init object
((number*)allocated)->move(); allocated->_type = type;
else if (allocated->_type == cmd_complex) allocated->_size = size;
((complex*)allocated)->move(); if (type == cmd_number)
((number*)allocated)->init();
else if (type == cmd_complex)
((complex*)allocated)->init();
return allocated;
}
object* pop_back(int pop_count = 1) {
object* back = NULL;
// pop several entries, return the last
while (pop_count-- > 0) {
if (_count > 0) {
_current = (char*)_base_pointer[--_count];
back = (object*)_current;
}
} }
// return back;
static void copy_and_push_back(object* from, stack& to, unsigned int size) }
{
// copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(size, from->_type);
memcpy(allocated, from, size);
if (allocated->_type == cmd_number) unsigned int size() { return _count; }
((number*)allocated)->move();
else if (allocated->_type == cmd_complex)
((complex*)allocated)->move();
}
object* allocate_back(unsigned int size, cmd_type_t type)
{
object* allocated;
bool data_is_reallocated = false;
char* old_base;
// manage data memory allocation (add as much as memory it is needed) // stack access (stack_level=0=first out)
if (((_current - _base) + size) > _total_size) object* get_obj(unsigned int stack_level) {
{ return seq_obj(_count - stack_level - 1);
// calc nb of needed pages }
unsigned long page_number = 1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
_total_size += page_number * ALLOC_STACK_CHUNK;
old_base = _base; object* operator[](unsigned int stack_level) {
_base = (char*)realloc(_base, _total_size); return seq_obj(_count - stack_level - 1);
}
_current = _base + (_current - old_base); object* back() {
data_is_reallocated = true; object* obj = NULL;
} if (_count > 0) obj = _base_pointer[_count - 1];
return obj;
}
// manage pointers memory allocation (add one page if needed) unsigned int get_len(unsigned int index) {
if ((_count + 1) > _total_count_pointer) return seq_len(_count - index - 1);
{ }
_base_pointer = (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
}
// recalc object pointers in case of base reallocation cmd_type_t get_type(unsigned int index) {
if (data_is_reallocated) return seq_type(_count - index - 1);
{ }
for(int i = 0; i < _count; i++)
{
_base_pointer[i] = (object*)(_base + ((char*)_base_pointer[i] - old_base));
if (_base_pointer[i]->_type == cmd_number)
((number*)_base_pointer[i])->move();
else if (_base_pointer[i]->_type == cmd_complex)
((complex*)_base_pointer[i])->move();
}
}
// manage stack itself // sequential access (index is counted from front)
_base_pointer[_count++] = (object*)_current; object* seq_obj(unsigned int index) {
allocated = (object*)_current; object* obj = NULL;
_current += size; if (index < _count) obj = _base_pointer[index];
return obj;
}
// init object unsigned int seq_len(unsigned int index) {
allocated->_type = type; unsigned int len = 0;
allocated->_size = size; if (index < _count) len = _base_pointer[index]->_size;
if (type == cmd_number) return len;
((number*)allocated)->init(); }
else if (type == cmd_complex)
((complex*)allocated)->init();
return allocated; cmd_type_t seq_type(unsigned int index) {
} cmd_type_t type = cmd_undef;
if (index < _count) type = _base_pointer[index]->_type;
return type;
}
object* pop_back(int pop_count = 1) private:
{ char* _base;
object* back = NULL; char* _current;
object** _base_pointer;
// pop several entries, return the last unsigned int _count; // stack count
while (pop_count-- > 0) unsigned int _total_count_pointer; // total number of possible pointers
{ unsigned int _total_size; // total allocated data size in bytes
if (_count > 0)
{
_current = (char*)_base_pointer[--_count];
back = (object*)_current;
}
}
return back;
}
unsigned int size()
{
return _count;
}
// stack access (stack_level=0=first out)
object* get_obj(unsigned int stack_level)
{
return seq_obj(_count - stack_level - 1);
}
object* operator[](unsigned int stack_level)
{
return seq_obj(_count - stack_level - 1);
}
object* back()
{
object* obj = NULL;
if (_count>0)
obj = _base_pointer[_count - 1];
return obj;
}
unsigned int get_len(unsigned int index)
{
return seq_len(_count - index - 1);
}
cmd_type_t get_type(unsigned int index)
{
return seq_type(_count - index - 1);
}
// sequential access (index is counted from front)
object* seq_obj(unsigned int index)
{
object* obj = NULL;
if (index<_count)
obj = _base_pointer[index];
return obj;
}
unsigned int seq_len(unsigned int index)
{
unsigned int len = 0;
if (index<_count)
len = _base_pointer[index]->_size;
return len;
}
cmd_type_t seq_type(unsigned int index)
{
cmd_type_t type = cmd_undef;
if (index<_count)
type = _base_pointer[index]->_type;
return type;
}
private:
char* _base;
char* _current;
object** _base_pointer;
unsigned int _count;//stack count
unsigned int _total_count_pointer;//total number of possible pointers
unsigned int _total_size;//total allocated data size in bytes
}; };
// //
class heap : public stack class heap : public stack {
{ public:
public: heap() {}
heap() { } virtual ~heap() {}
virtual ~heap() { }
object* add(const string name, object* obj, unsigned int size) object* add(const string name, object* obj, unsigned int size) {
{ map<string, unsigned int>::iterator i = _map.find(name);
map<string, unsigned int>::iterator i = _map.find(name); object* local = NULL;
object* local = NULL;
// variable does not exist in heap or already exists but its size is too short -> allocate // variable does not exist in heap or already exists but its size is too
if (i!=_map.end()) // short -> allocate
local = seq_obj(i->second); if (i != _map.end()) local = seq_obj(i->second);
if (local==NULL || (local!=NULL && size>local->_size)) if (local == NULL || (local != NULL && size > local->_size)) {
{ copy_and_push_back(obj, *this, size);
copy_and_push_back(obj, *this, size); _map[name] = ((stack*)this)->size() - 1;
_map[name] = ((stack*)this)->size()-1; } else {
} // variable already exists in heap but previous was larger -> don't
else // reallocate copy a whole stack entry and push it back to another stack
{ memcpy(local, obj, size);
// variable already exists in heap but previous was larger -> don't reallocate if (local->_type == cmd_number)
// copy a whole stack entry and push it back to another stack ((number*)local)->move();
memcpy(local, obj, size); else if (local->_type == cmd_complex)
if (local->_type == cmd_number) ((complex*)local)->move();
((number*)local)->move();
else if (local->_type == cmd_complex)
((complex*)local)->move();
}
return local;
}
bool get(const string name, object*& obj, unsigned int& size)
{
bool ret = false;
map<string, unsigned int>::iterator i = _map.find(name);
if (i!=_map.end())
{
obj = seq_obj(i->second);
size = obj->_size;
ret = true;
}
return ret;
} }
bool replace_value(const string name, object* obj, unsigned int size) return local;
{ }
bool ret=false;
map<string, unsigned int>::iterator i = _map.find(name);
if (i!=_map.end()) bool get(const string name, object*& obj, unsigned int& size) {
{ bool ret = false;
object* obj_dst = seq_obj(i->second); map<string, unsigned int>::iterator i = _map.find(name);
if (size<=obj_dst->_size)
{ if (i != _map.end()) {
(void)memcpy(obj_dst, obj, size); obj = seq_obj(i->second);
if (obj_dst->_type == cmd_number) size = obj->_size;
((number*)obj_dst)->move(); ret = true;
else if (obj_dst->_type == cmd_complex)
((complex*)obj_dst)->move();
ret = true;
}
}
} }
return ret;
}
bool exist(const string name) bool replace_value(const string name, object* obj, unsigned int size) {
{ bool ret = false;
return (_map.find(name) != _map.end()); map<string, unsigned int>::iterator i = _map.find(name);
if (i != _map.end()) {
object* obj_dst = seq_obj(i->second);
if (size <= obj_dst->_size) {
(void)memcpy(obj_dst, obj, size);
if (obj_dst->_type == cmd_number)
((number*)obj_dst)->move();
else if (obj_dst->_type == cmd_complex)
((complex*)obj_dst)->move();
ret = true;
}
} }
}
bool get_by_index(int num, string& name, object*& obj, unsigned int& size) bool exist(const string name) { return (_map.find(name) != _map.end()); }
{
if (num>=0 && num<(int)_map.size())
{
object* local;
map<string, unsigned int>::iterator i= _map.begin();
for(int j = 0; j < num; j++) bool get_by_index(int num, string& name, object*& obj, unsigned int& size) {
i++; if (num >= 0 && num < (int)_map.size()) {
object* local;
map<string, unsigned int>::iterator i = _map.begin();
local = (object*)seq_obj(i->second); for (int j = 0; j < num; j++) i++;
name = i->first;
obj = local; local = (object*)seq_obj(i->second);
size = local->_size; name = i->first;
return true; obj = local;
} size = local->_size;
else return true;
return false; } else
return false;
}
bool erase(const string& name) {
map<string, unsigned int>::iterator i = _map.find(name);
bool ret = false;
if (i != _map.end()) {
// remove variable from map
_map.erase(i->first);
ret = true;
// TODO: remove unused stack entries
} }
return ret;
}
bool erase(const string& name) void erase_all(void) {
{ // map
map<string, unsigned int>::iterator i = _map.find(name); _map.erase(_map.begin(), _map.end());
bool ret = false;
if (i != _map.end())
{
// remove variable from map
_map.erase(i->first);
ret = true;
// TODO: remove unused stack entries
}
return ret;
}
void erase_all(void)
{
// map
_map.erase(_map.begin(), _map.end());
// and stack // and stack
((stack*)this)->erase(); ((stack*)this)->erase();
} }
unsigned int count_vars() { return _map.size(); } unsigned int count_vars() { return _map.size(); }
private: private:
map<string, unsigned int> _map; map<string, unsigned int> _map;
}; };
#endif // __stack_h__ #endif // __stack_h__

View file

@ -15,8 +15,9 @@ static const char description[] =
"using " ATTR_BOLD "GMP" ATTR_OFF " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" "using " ATTR_BOLD "GMP" ATTR_OFF " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n"
ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING " under GNU LGPL\n"
"and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n"; "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n";
// syntax // syntax
static const char syntax[] = static const char syntax[] =
ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\n" ATTR_BOLD "Syntax" ATTR_OFF
"with optional command = list of commands"; ": rpn [command]\n"
"with optional command = list of commands";