#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
#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
// constants
@ -42,37 +43,46 @@
#define MPFR_FORMAT_SCI "Re"
#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
//
typedef enum {
ret_ok,
ret_unknown_err,
ret_missing_operand,
ret_bad_operand_type,
ret_out_of_range,
ret_unknown_variable,
ret_internal,
ret_deadly,
ret_good_bye,
ret_not_impl,
ret_nop,
ret_syntax,
ret_div_by_zero,
ret_runtime_error,
ret_abort_current_entry,
ret_max
ret_ok,
ret_unknown_err,
ret_missing_operand,
ret_bad_operand_type,
ret_out_of_range,
ret_unknown_variable,
ret_internal,
ret_deadly,
ret_good_bye,
ret_not_impl,
ret_nop,
ret_syntax,
ret_div_by_zero,
ret_runtime_error,
ret_abort_current_entry,
ret_max
} ret_value;
#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" \
}
#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" \
}
// 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
#define HISTORY_FILE ".rpn_history"
@ -99,14 +109,14 @@ typedef enum {
#error "Invalid MPFR Exp format"
#endif
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(h,i) ((h) > (i) ? (h) : (i))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(h, i) ((h) > (i) ? (h) : (i))
#define MPFR_EXP_INF (MPFR_EXP_MIN+3)
#define MPFR_EXP_NAN (MPFR_EXP_MIN+2)
#define MPFR_EXP_INF (MPFR_EXP_MIN + 3)
#define MPFR_EXP_NAN (MPFR_EXP_MIN + 2)
#define MPFR_EXP(x) ((x)->_mpfr_exp)
#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_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF)
#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0)

View file

@ -2,97 +2,92 @@
#define DEBUG_H
static void dump8(unsigned char* to_dump, unsigned long offset,
unsigned long size)
{
const int block_size = 1;
const int block_per_line = 16;
int max_line = size / block_size;
unsigned char mychar;
int i;
int j;
for (i = 0; i < max_line; i++)
{
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)
{
unsigned long size) {
const int block_size = 1;
const int block_per_line = 16;
int max_line = size / block_size;
unsigned char mychar;
int i;
int j;
for (i = 0; i < max_line; i++) {
if ((i % block_per_line) == 0) {
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);
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("\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
#include <time.h>
static int chrono_next = 0;
static struct
{
struct timespec ts_point;
char comment[256];
static struct {
struct timespec ts_point;
char comment[256];
} chrono_point[24];
static void chrono_start()
{
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
strcpy(chrono_point[0].comment, "START");
chrono_next = 1;
static void chrono_start() {
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
strcpy(chrono_point[0].comment, "START");
chrono_next = 1;
}
static void chrono_add(const char* comment)
{
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
strcpy(chrono_point[chrono_next].comment, comment);
chrono_next++;
static void chrono_add(const char* comment) {
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
strcpy(chrono_point[chrono_next].comment, comment);
chrono_next++;
}
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 to = (uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
return to - from;
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 to =
(uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
return to - from;
}
static void chrono_all_print(void)
{
for(int i = 1; i < chrono_next; i++)
{
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[i-1].ts_point, &chrono_point[i].ts_point), chrono_point[i].comment);
}
static void chrono_all_print(void) {
for (int i = 1; i < chrono_next; i++) {
printf("CHRONO [%lu us] %s\n",
chrono_diff_us(&chrono_point[i - 1].ts_point,
&chrono_point[i].ts_point),
chrono_point[i].comment);
}
}
static void chrono_print(int chrono)
{
if (chrono >= 1)
{
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[chrono-1].ts_point, &chrono_point[chrono].ts_point), chrono_point[chrono].comment);
}
static void chrono_print(int chrono) {
if (chrono >= 1) {
printf("CHRONO [%lu us] %s\n",
chrono_diff_us(&chrono_point[chrono - 1].ts_point,
&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

View file

@ -1,12 +1,12 @@
// std c
#include <signal.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 <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
// internal includes
#include "program.hpp"
@ -16,149 +16,137 @@ static stack s_global_stack;
static program* s_prog_to_interrupt = NULL;
// actions to be done at rpn exit
void exit_interactive_rpn()
{
struct passwd* pw = getpwuid(getuid());
if (pw != NULL)
{
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
void exit_interactive_rpn() {
struct passwd* pw = getpwuid(getuid());
if (pw != NULL) {
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
// trunc current history
ofstream history(history_path, ios_base::out|ios_base::trunc);
history.close();
// trunc current history
ofstream history(history_path, ios_base::out | ios_base::trunc);
history.close();
// save it
if (linenoiseHistorySave(history_path) != 0)
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno));
}
// save it
if (linenoiseHistorySave(history_path) != 0)
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n",
history_path, errno, strerror(errno));
}
}
// actions to be done at rpn exit
void init_interactive_rpn()
{
struct passwd* pw = getpwuid(getuid());
if (pw != NULL)
{
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
void init_interactive_rpn() {
struct passwd* pw = getpwuid(getuid());
if (pw != NULL) {
char history_path[PATH_MAX];
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
// don't care about errors
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
linenoiseHistoryLoad(history_path);
}
// don't care about errors
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
linenoiseHistoryLoad(history_path);
}
}
// handle CtrlC signal
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context)
{
if (s_prog_to_interrupt != NULL)
{
s_prog_to_interrupt->stop();
s_prog_to_interrupt = NULL;
}
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
if (s_prog_to_interrupt != NULL) {
s_prog_to_interrupt->stop();
s_prog_to_interrupt = NULL;
}
exit_interactive_rpn();
exit_interactive_rpn();
}
// handle SIGSEGV signal
static void segv_handler(int sig, siginfo_t* siginfo, void* context)
{
fprintf(stderr, "Internal error\n");
s_prog_to_interrupt->stop();
s_prog_to_interrupt = NULL;
static void segv_handler(int sig, siginfo_t* siginfo, void* context) {
fprintf(stderr, "Internal error\n");
s_prog_to_interrupt->stop();
s_prog_to_interrupt = NULL;
}
static void catch_signals(program* prog)
{
struct sigaction act;
static void catch_signals(program* prog) {
struct sigaction act;
s_prog_to_interrupt = prog;
s_prog_to_interrupt = prog;
act.sa_sigaction = &ctrlc_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']", errno, strerror(errno));
act.sa_sigaction = &ctrlc_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']",
errno, strerror(errno));
act.sa_sigaction = &segv_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno));
act.sa_sigaction = &segv_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0)
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']",
errno, strerror(errno));
}
//
int main(int argc, char* argv[])
{
int ret = 0;
bool go_on = true;
int main(int argc, char* argv[]) {
int ret = 0;
bool go_on = true;
// apply default configuration
program::apply_default();
// apply default configuration
program::apply_default();
// run with interactive prompt
if (argc == 1)
{
// init history
init_interactive_rpn();
// run with interactive prompt
if (argc == 1) {
// init history
init_interactive_rpn();
// entry loop
while(go_on)
{
// make program from interactive entry
program prog;
switch (program::entry(prog))
{
case ret_good_bye:
go_on = false;
break;
case ret_abort_current_entry:
break;
default:
// user could stop prog with CtrlC
catch_signals(&prog);
// entry loop
while (go_on) {
// make program from interactive entry
program prog;
switch (program::entry(prog)) {
case ret_good_bye:
go_on = false;
break;
case ret_abort_current_entry:
break;
default:
// user could stop prog with CtrlC
catch_signals(&prog);
// run it
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
go_on = false;
else
program::show_stack(s_global_stack);
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);
}
// run it
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
go_on = false;
else
program::show_stack(s_global_stack);
break;
}
}
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 <string>
using namespace std;
#include "mpfr.h"
#include "constant.h"
#include "mpfr.h"
#include "object.hpp"
// 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;
static bool is_min(mpfr_t p, mpfr_prec_t prec)
{
// see mpfr_vasprintf code
bool ret;
int round_away;
switch (floating_t::s_mpfr_rnd)
{
case MPFR_RNDA:
round_away = 1;
break;
case MPFR_RNDD:
round_away = MPFR_IS_NEG (p);
break;
case MPFR_RNDU:
round_away = MPFR_IS_POS (p);
break;
case MPFR_RNDN:
{
/* compare |p| to y = 0.5*10^(-prec) */
mpfr_t y;
mpfr_exp_t e = MAX (MPFR_PREC (p), 56);
mpfr_init2 (y, e + 8);
do
{
/* find a lower approximation of
0.5*10^(-prec) different from |p| */
e += 8;
mpfr_set_prec (y, e);
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);
static bool is_min(mpfr_t p, mpfr_prec_t prec) {
// see mpfr_vasprintf code
bool ret;
int round_away;
switch (floating_t::s_mpfr_rnd) {
case MPFR_RNDA:
round_away = 1;
break;
case MPFR_RNDD:
round_away = MPFR_IS_NEG(p);
break;
case MPFR_RNDU:
round_away = MPFR_IS_POS(p);
break;
case MPFR_RNDN: {
/* compare |p| to y = 0.5*10^(-prec) */
mpfr_t y;
mpfr_exp_t e = MAX(MPFR_PREC(p), 56);
mpfr_init2(y, e + 8);
do {
/* find a lower approximation of
0.5*10^(-prec) different from |p| */
e += 8;
mpfr_set_prec(y, e);
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;
mpfr_clear (y);
}
break;
default:
round_away = 0;
}
round_away = mpfr_cmpabs(y, p) < 0;
mpfr_clear(y);
} break;
default:
round_away = 0;
}
if (round_away)
/* round away from zero: the last output digit is '1' */
ret = true;
else
/* only zeros in fractional part */
ret = false;
return ret;
if (round_away) /* round away from zero: the last output digit is '1' */
ret = true;
else
/* only zeros in fractional part */
ret = false;
return ret;
}
static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL)
{
// see mpfr_vasprintf code
mpfr_exp_t exp = mpfr_get_exp(real);
int digits = 0; //forced 0 digits after separator
int i;
static void print_fix(FILE* stream, mpfr_t real, int base,
const char* write_after_sign = NULL) {
// see mpfr_vasprintf code
mpfr_exp_t exp = mpfr_get_exp(real);
int digits = 0; // forced 0 digits after separator
int i;
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real)))
{
if (MPFR_IS_NAN(real))
fputs("nan", stream);
else if (MPFR_IS_INF(real))
{
if (MPFR_IS_NEG(real))
fputc('-', stream);
fputs("inf", stream);
}
else
{
// zero
if (MPFR_IS_NEG(real))
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);
}
}
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) {
if (MPFR_IS_NAN(real))
fputs("nan", stream);
else if (MPFR_IS_INF(real)) {
if (MPFR_IS_NEG(real)) fputc('-', stream);
fputs("inf", stream);
} else {
// zero
if (MPFR_IS_NEG(real)) 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)
{
if (MPFR_IS_NEG(real))
fputc('-', stream);
if (write_after_sign != NULL)
fputs(write_after_sign, stream);
} else if (exp < -digits) {
if (MPFR_IS_NEG(real)) fputc('-', stream);
if (write_after_sign != NULL) fputs(write_after_sign, stream);
fputc('0', stream);
if (digits > 0) {
fputc('.', stream);
for (i = 0; i < digits - 1; i++) fputc('0', stream);
if (is_min(real, digits))
fputc('1', stream);
else
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);
for (i = 0; i< digits - 1; i++)
fputc('0', stream);
if (is_min(real, digits))
fputc('1', stream);
else
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);
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);
}
}
}
void object::show(FILE* stream)
{
int digits;
char* str;
char base[32];
void object::show(FILE* stream) {
int digits;
char* str;
char base[32];
switch(_type)
{
switch (_type) {
case cmd_number:
switch(((number*)this)->_representation)
{
case number::dec:
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr);
break;
case number::hex:
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
break;
case number::bin:
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
break;
case number::base:
sprintf(base, "%db", ((number*)this)->_base);
print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base, base);
break;
default:
fprintf(stream, "<unknown number representation>");
break;
}
break;
switch (((number*)this)->_representation) {
case number::dec:
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
((number*)this)->_value.mpfr);
break;
case number::hex:
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
break;
case number::bin:
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
break;
case number::base:
sprintf(base, "%db", ((number*)this)->_base);
print_fix(stream, ((number*)this)->_value.mpfr,
((number*)this)->_base, base);
break;
default:
fprintf(stream, "<unknown number representation>");
break;
}
break;
case cmd_complex:
switch(((complex*)this)->_representation)
{
case number::dec:
fprintf(stream, "(");
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr);
fprintf(stream, ",");
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->im()->mpfr);
fprintf(stream, ")");
break;
case number::hex:
fprintf(stream, "(");
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->re()->mpfr);
fprintf(stream, ",");
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->im()->mpfr);
fprintf(stream, ")");
break;
default:
fprintf(stream, "<unknown complex representation>");
}
break;
switch (((complex*)this)->_representation) {
case number::dec:
fprintf(stream, "(");
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
((complex*)this)->re()->mpfr);
fprintf(stream, ",");
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
((complex*)this)->im()->mpfr);
fprintf(stream, ")");
break;
case number::hex:
fprintf(stream, "(");
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
((complex*)this)->re()->mpfr);
fprintf(stream, ",");
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
((complex*)this)->im()->mpfr);
fprintf(stream, ")");
break;
default:
fprintf(stream, "<unknown complex representation>");
}
break;
case cmd_string:
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
break;
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
break;
case cmd_program:
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
break;
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
break;
case cmd_symbol:
fprintf(stream, "'%s'", ((symbol*)this)->_value);
break;
fprintf(stream, "'%s'", ((symbol*)this)->_value);
break;
case cmd_keyword:
case cmd_branch:
fprintf(stream, "%s", ((keyword*)this)->_value);
break;
fprintf(stream, "%s", ((keyword*)this)->_value);
break;
default:
fprintf(stream, "< unknown object representation >");
break;
}
fprintf(stream, "< unknown object representation >");
break;
}
}

View file

@ -7,15 +7,15 @@
// definitions for objects
////
typedef enum {
cmd_undef,
cmd_number,// floating point number
cmd_complex,// complex, couple of floating point numbers
cmd_string,// string like "string"
cmd_symbol,// symbol like 'symbol'
cmd_program,// program like << instructions >>
cmd_keyword,// langage keyword
cmd_branch,// langage branch keyword
cmd_max
cmd_undef,
cmd_number, // floating point number
cmd_complex, // complex, couple of floating point numbers
cmd_string, // string like "string"
cmd_symbol, // symbol like 'symbol'
cmd_program, // program like << instructions >>
cmd_keyword, // langage keyword
cmd_branch, // langage branch keyword
cmd_max
} cmd_type_t;
class program;
@ -26,330 +26,262 @@ typedef int (program::*branch_fn_t)(branch&);
// MPFR object
////
struct floating_t
{
mpfr_prec_t mpfr_prec;// precision in bits
unsigned int mpfr_prec_bytes;// significand storing length in bytes
mpfr_t mpfr;//mpfr object
struct floating_t {
mpfr_prec_t mpfr_prec; // precision in bits
unsigned int mpfr_prec_bytes; // significand storing length in bytes
mpfr_t mpfr; // mpfr object
void init()
{
void* significand = (void*)(this+1);
mpfr_prec = s_mpfr_prec;
mpfr_prec_bytes = s_mpfr_prec_bytes;
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
}
void init() {
void* significand = (void*)(this + 1);
mpfr_prec = s_mpfr_prec;
mpfr_prec_bytes = s_mpfr_prec_bytes;
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
}
void move()
{
void* significand = (void*)(this+1);
mpfr_custom_move(mpfr, significand);
}
void move() {
void* significand = (void*)(this + 1);
mpfr_custom_move(mpfr, significand);
}
floating_t& operator=(const double val)
{
mpfr_set_d(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); }
floating_t& operator=(const long int val)
{
mpfr_set_si(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const long int val) {
mpfr_set_si(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const unsigned long val)
{
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const unsigned long val) {
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
}
operator double()
{
return mpfr_get_d(mpfr, s_mpfr_rnd);
}
operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); }
operator int()
{
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
}
operator long()
{
return mpfr_get_si(mpfr, s_mpfr_rnd);
}
operator int() { return (int)mpfr_get_si(mpfr, s_mpfr_rnd); }
bool operator>(const floating_t right)
{
return mpfr_cmp(mpfr, right.mpfr) > 0;
}
operator long() { return mpfr_get_si(mpfr, s_mpfr_rnd); }
bool operator<(const floating_t right)
{
return mpfr_cmp(mpfr, right.mpfr) < 0;
}
bool operator>(const floating_t right) {
return mpfr_cmp(mpfr, right.mpfr) > 0;
}
// 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];
bool operator<(const floating_t right) {
return mpfr_cmp(mpfr, right.mpfr) < 0;
}
// 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
////
struct object
{
// object type
cmd_type_t _type;
unsigned int _size;
struct object {
// object type
cmd_type_t _type;
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
////
struct number : public object
{
// members
enum {
dec,
hex,
bin,
base
} _representation;
// base
// carefull: _base is used only if _representation = base
int _base;
// mind that float value is at the end of the object
// because its mantissa is just after the obj in memory
floating_t _value;
struct number : public object {
// members
enum { dec, hex, bin, base } _representation;
// base
// carefull: _base is used only if _representation = base
int _base;
// mind that float value is at the end of the object
// because its mantissa is just after the obj in memory
floating_t _value;
// publics
number() { _type = cmd_number; }
// publics
number() { _type = cmd_number; }
void init()
{
_type = cmd_number;
_representation = dec;
_value.init();
}
void init() {
_type = cmd_number;
_representation = dec;
_value.init();
}
void move()
{
_value.move();
}
void move() { _value.move(); }
void set(unsigned long value)
{
_type = cmd_number;
_value = value;
}
void set(unsigned long value) {
_type = cmd_number;
_value = value;
}
static unsigned int calc_size()
{
return (unsigned int)(sizeof(number)+floating_t::s_mpfr_prec_bytes);
}
static unsigned int calc_size() {
return (unsigned int)(sizeof(number) + floating_t::s_mpfr_prec_bytes);
}
// representation mode
typedef enum {
std,
fix,
sci
} mode_enum;
static mode_enum s_mode;
// representation mode
typedef enum { std, fix, sci } mode_enum;
static mode_enum s_mode;
// precision
static int s_decimal_digits;
static string s_mpfr_printf_format;
// precision
static int s_decimal_digits;
static string s_mpfr_printf_format;
};
// stack objects derived from object
////
struct complex : public object
{
enum {
dec,
hex
} _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;
struct complex : public object {
enum { dec, hex } _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
floating_t* re() { return &_re; }
floating_t* im() { return (floating_t*)((char*)&_re + sizeof(floating_t) + _re.mpfr_prec_bytes); }
// re and im float values are at the end of the object
floating_t* re() { return &_re; }
floating_t* im() {
return (floating_t*)((char*)&_re + sizeof(floating_t) +
_re.mpfr_prec_bytes);
}
void init()
{
_type = cmd_complex;
_representation = dec;
re()->init();
im()->init();
}
void init() {
_type = cmd_complex;
_representation = dec;
re()->init();
im()->init();
}
void move()
{
re()->move();
im()->move();
}
void move() {
re()->move();
im()->move();
}
static unsigned int calc_size()
{
return (unsigned int)(sizeof(complex)+2*(sizeof(floating_t)+floating_t::s_mpfr_prec_bytes));
}
static unsigned int calc_size() {
return (
unsigned int)(sizeof(complex) +
2 * (sizeof(floating_t) + floating_t::s_mpfr_prec_bytes));
}
};
struct ostring : public object
{
// ostring may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len)
{
_type = cmd_string;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
{
_value[_len] = 0;
_len = 0;
}
struct ostring : public object {
// ostring may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len) {
_type = cmd_string;
if (value != NULL) {
if (len > 0) (void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
} else {
_value[_len] = 0;
_len = 0;
}
}
// length of _value, not including the terminal '\0'
unsigned int _len;
char _value[0];
// length of _value, not including the terminal '\0'
unsigned int _len;
char _value[0];
};
struct oprogram : public object
{
// oprogram may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len)
{
_type = cmd_program;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
struct oprogram : public object {
// oprogram may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len) {
_type = cmd_program;
if (value != NULL) {
if (len > 0) (void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
} else {
_value[0] = 0;
_len = 0;
}
}
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
};
struct symbol : public object
{
// symbol may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len, bool auto_eval)
{
_type = cmd_symbol;
_auto_eval = auto_eval;
struct symbol : public object {
// symbol may first have been allocated with len+1 bytes
void set(const char* value, unsigned int len, bool auto_eval) {
_type = cmd_symbol;
_auto_eval = auto_eval;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
if (value != NULL) {
if (len > 0) (void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
} else {
_value[0] = 0;
_len = 0;
}
}
//
bool _auto_eval;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
//
bool _auto_eval;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
};
struct keyword : public object
{
// keyword may first have been allocated with len+1 bytes
void set(program_fn_t fn, const char* value, unsigned int len)
{
_type = cmd_keyword;
_fn = fn;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
struct keyword : public object {
// keyword may first have been allocated with len+1 bytes
void set(program_fn_t fn, const char* value, unsigned int len) {
_type = cmd_keyword;
_fn = fn;
if (value != NULL) {
if (len > 0) (void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
} else {
_value[0] = 0;
_len = 0;
}
}
//
program_fn_t _fn;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
//
program_fn_t _fn;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
};
struct branch : public object
{
//
void set(branch_fn_t fn, const char* value, unsigned int len)
{
_type = cmd_branch;
_fn = fn;
arg1 = -1;
arg2 = -1;
arg3 = -1;
farg1 = NULL;
farg2 = NULL;
arg_bool = 0;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
{
_value[0] = 0;
_len = 0;
}
struct branch : public object {
//
void set(branch_fn_t fn, const char* value, unsigned int len) {
_type = cmd_branch;
_fn = fn;
arg1 = -1;
arg2 = -1;
arg3 = -1;
farg1 = NULL;
farg2 = NULL;
arg_bool = 0;
if (value != NULL) {
if (len > 0) (void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
} else {
_value[0] = 0;
_len = 0;
}
}
// branch function
branch_fn_t _fn;
// args used by cmd_branch cmds
int arg1, arg2, arg3;
number *farg1, *farg2;
bool arg_bool;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
// branch function
branch_fn_t _fn;
// args used by cmd_branch cmds
int arg1, arg2, arg3;
number *farg1, *farg2;
bool arg_bool;
// length of _value, not includiong the terminal '\0'
unsigned int _len;
char _value[0];
};
#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;
//
program::keyword_t program::s_keywords[] =
{
//GENERAL
{ cmd_undef, "", NULL, "\nGENERAL"},
{ cmd_keyword, "nop", &program::rpn_nop, "no operation"},
{ cmd_keyword, "help", &program::rpn_help, "this help message" },
{ cmd_keyword, "h", &program::rpn_help, "" },
{ cmd_keyword, "?", &program::rpn_help, "" },
{ cmd_keyword, "quit", &program::rpn_good_bye, "quit software" },
{ cmd_keyword, "q", &program::rpn_good_bye, "" },
{ cmd_keyword, "exit", &program::rpn_good_bye, "" },
{ cmd_keyword, "test", &program::rpn_test, "" }, //not seen by user
{ cmd_keyword, "version", &program::rpn_version, "show rpn version" },
{ cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string" },
{ cmd_keyword, "history", &program::rpn_history, "see commands history" },
program::keyword_t program::s_keywords[] = {
// GENERAL
{cmd_undef, "", NULL, "\nGENERAL"},
{cmd_keyword, "nop", &program::rpn_nop, "no operation"},
{cmd_keyword, "help", &program::rpn_help, "this help message"},
{cmd_keyword, "h", &program::rpn_help, ""},
{cmd_keyword, "?", &program::rpn_help, ""},
{cmd_keyword, "quit", &program::rpn_good_bye, "quit software"},
{cmd_keyword, "q", &program::rpn_good_bye, ""},
{cmd_keyword, "exit", &program::rpn_good_bye, ""},
{cmd_keyword, "test", &program::rpn_test, ""}, // not seen by user
{cmd_keyword, "version", &program::rpn_version, "show rpn version"},
{cmd_keyword, "uname", &program::rpn_uname,
"show rpn complete identification string"},
{cmd_keyword, "history", &program::rpn_history, "see commands history"},
//USUAL OPERATIONS ON REALS AND COMPLEXES
{ cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
{ cmd_keyword, "+", &program::rpn_plus, "addition" },
{ cmd_keyword, "-", &program::rpn_minus, "substraction" },
{ cmd_keyword, "chs", &program::rpn_neg , "negation" },
{ cmd_keyword, "neg", &program::rpn_neg , "" },
{ cmd_keyword, "*", &program::rpn_mul, "multiplication" },
{ cmd_keyword, "/", &program::rpn_div, "division" },
{ cmd_keyword, "inv", &program::rpn_inv, "inverse" },
{ cmd_keyword, "^", &program::rpn_power, "power" },
{ cmd_keyword, "pow", &program::rpn_power, "" },
{ cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root" },
{ cmd_keyword, "sq", &program::rpn_square, "rpn_square" },
{ cmd_keyword, "sqr", &program::rpn_square, "" },
{ cmd_keyword, "abs", &program::rpn_abs, "absolute value" },
{ cmd_keyword, "dec", &program::rpn_dec, "decimal representation" },
{ cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation" },
{ cmd_keyword, "bin", &program::rpn_bin, "decimal 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" },
// USUAL OPERATIONS ON REALS AND COMPLEXES
{cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
{cmd_keyword, "+", &program::rpn_plus, "addition"},
{cmd_keyword, "-", &program::rpn_minus, "substraction"},
{cmd_keyword, "chs", &program::rpn_neg, "negation"},
{cmd_keyword, "neg", &program::rpn_neg, ""},
{cmd_keyword, "*", &program::rpn_mul, "multiplication"},
{cmd_keyword, "/", &program::rpn_div, "division"},
{cmd_keyword, "inv", &program::rpn_inv, "inverse"},
{cmd_keyword, "^", &program::rpn_power, "power"},
{cmd_keyword, "pow", &program::rpn_power, ""},
{cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
{cmd_keyword, "sq", &program::rpn_square, "rpn_square"},
{cmd_keyword, "sqr", &program::rpn_square, ""},
{cmd_keyword, "abs", &program::rpn_abs, "absolute value"},
{cmd_keyword, "dec", &program::rpn_dec, "decimal representation"},
{cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"},
{cmd_keyword, "bin", &program::rpn_bin, "decimal 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"},
//OPERATIONS ON REALS
{ cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
{ cmd_keyword, "%", &program::rpn_purcent, "purcent" },
{ cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent" },
{ 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, "mant", &program::rpn_mant, "mantissa of a real number" },
{ cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number" },
{ cmd_keyword, "floor", &program::rpn_floor, "largest number <=" },
{ cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >=" },
{ cmd_keyword, "ip", &program::rpn_ip, "integer part" },
{ cmd_keyword, "fp", &program::rpn_fp, "fractional part" },
{ cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers" },
{ cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers" },
// OPERATIONS ON REALS
{cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
{cmd_keyword, "%", &program::rpn_purcent, "purcent"},
{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
{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, "mant", &program::rpn_mant, "mantissa of a real number"},
{cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
{cmd_keyword, "floor", &program::rpn_floor, "largest number <="},
{cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="},
{cmd_keyword, "ip", &program::rpn_ip, "integer part"},
{cmd_keyword, "fp", &program::rpn_fp, "fractional part"},
{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
{ cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
{ cmd_keyword, "re", &program::rpn_re, "complex real part" },
{ cmd_keyword, "im", &program::rpn_im, "complex imaginary part" },
{ cmd_keyword, "conj", &program::rpn_conj, "complex conjugate" },
{ 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, "r->c", &program::rpn_r2c, "transform 2 reals in a complex" },
{ cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar" },
{ cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian" },
// nOPERATIONS ON COMPLEXES
{cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
{cmd_keyword, "re", &program::rpn_re, "complex real part"},
{cmd_keyword, "im", &program::rpn_im, "complex imaginary part"},
{cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"},
{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, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
{cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
{cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
//MODE
{ cmd_undef, "", NULL, "\nMODE"},
{ cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std" },
{ cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix" },
{ cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci" },
{ 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" },
// MODE
{cmd_undef, "", NULL, "\nMODE"},
{cmd_keyword, "std", &program::rpn_std,
"standard floating numbers representation. ex: std"},
{cmd_keyword, "fix", &program::rpn_fix,
"fixed point representation. ex: 6 fix"},
{cmd_keyword, "sci", &program::rpn_sci,
"scientific floating point representation. ex: 20 sci"},
{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
{ cmd_undef, "", NULL, "\nTEST"},
{ cmd_keyword, ">", &program::rpn_sup, "binary operator >" },
{ cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >=" },
{ cmd_keyword, "<", &program::rpn_inf, "binary operator <" },
{ cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <=" },
{ cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)" },
{ cmd_keyword, "==", &program::rpn_eq , "binary operator == (equal)" },
{ cmd_keyword, "and", &program::rpn_test_and , "boolean operator and" },
{ cmd_keyword, "or", &program::rpn_test_or , "boolean operator or" },
{ cmd_keyword, "xor", &program::rpn_test_xor , "boolean operator xor" },
{ cmd_keyword, "not", &program::rpn_test_not , "boolean operator not" },
{ cmd_keyword, "same", &program::rpn_same , "boolean operator same (equal)" },
// TESTS
{cmd_undef, "", NULL, "\nTEST"},
{cmd_keyword, ">", &program::rpn_sup, "binary operator >"},
{cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="},
{cmd_keyword, "<", &program::rpn_inf, "binary operator <"},
{cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="},
{cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"},
{cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"},
{cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"},
{cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"},
{cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
{cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"},
{cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"},
//STACK
{ cmd_undef, "", NULL, "\nSTACK"},
{ cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries" },
{ cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry" },
{ cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 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, "erase", &program::rpn_erase, "" },
{ cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries" },
{ cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry" },
{ cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries" },
{ cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries" },
{ cmd_keyword, "pick", &program::rpn_pick, "push a copy of the given stack level 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" },
// STACK
{cmd_undef, "", NULL, "\nSTACK"},
{cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
{cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"},
{cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 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, "erase", &program::rpn_erase, ""},
{cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
{cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
{cmd_keyword, "dup2", &program::rpn_dup2,
"duplicate 2 first stack entries"},
{cmd_keyword, "dupn", &program::rpn_dupn,
"duplicate n first stack entries"},
{cmd_keyword, "pick", &program::rpn_pick,
"push a copy of the given stack level 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
{ cmd_undef, "", NULL, "\nSTRING"},
{ cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string" },
{ cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object" },
{ cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string" },
{ 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" },
// STRING
{cmd_undef, "", NULL, "\nSTRING"},
{cmd_keyword, "->str", &program::rpn_instr,
"convert an object into a string"},
{cmd_keyword, "str->", &program::rpn_strout,
"convert a string into an object"},
{cmd_keyword, "chr", &program::rpn_chr,
"convert ASCII character code in stack level 1 into a string"},
{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
{ 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, "then", (program_fn_t)&program::rpn_then, "used with if" },
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" },
{ cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" },
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step" },
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "<start> <end> for <variable> <instructions> next|<step> step" },
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" },
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for" },
{ cmd_keyword, "ift", &program::rpn_ift, "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, "" },
// BRANCH
{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, "then", (program_fn_t)&program::rpn_then, "used with if"},
{cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"},
{cmd_branch, "end", (program_fn_t)&program::rpn_end,
"used with various branch instructions"},
{cmd_branch, "start", (program_fn_t)&program::rpn_start,
"<start> <end> start <instructions> next|<step> step"},
{cmd_branch, "for", (program_fn_t)&program::rpn_for,
"<start> <end> for <variable> <instructions> next|<step> step"},
{cmd_branch, "next", (program_fn_t)&program::rpn_next,
"used with start and for"},
{cmd_branch, "step", (program_fn_t)&program::rpn_step,
"used with start and for"},
{cmd_keyword, "ift", &program::rpn_ift,
"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
{ cmd_undef, "", NULL, "\nSTORE"},
{ cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto" },
{ cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl" },
{ cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge" },
{ cmd_keyword, "vars", &program::rpn_vars, "list all variables" },
{ cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables" },
{ cmd_keyword, "edit", &program::rpn_edit, "edit a variable content" },
{ cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+" },
{ 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" },
// STORE
{cmd_undef, "", NULL, "\nSTORE"},
{cmd_keyword, "sto", &program::rpn_sto,
"store a variable. ex: 1 'name' sto"},
{cmd_keyword, "rcl", &program::rpn_rcl,
"recall a variable. ex: 'name' rcl"},
{cmd_keyword, "purge", &program::rpn_purge,
"delete a variable. ex: 'name' purge"},
{cmd_keyword, "vars", &program::rpn_vars, "list all variables"},
{cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"},
{cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"},
{cmd_keyword, "sto+", &program::rpn_stoadd,
"add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
{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
{ cmd_undef, "", NULL, "\nPROGRAM"},
{ cmd_keyword, "eval", &program::rpn_eval, "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 >> >>" },
// PROGRAM
{cmd_undef, "", NULL, "\nPROGRAM"},
{cmd_keyword, "eval", &program::rpn_eval,
"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
{ cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
{ cmd_keyword, "pi", &program::rpn_pi, "pi constant" },
{ cmd_keyword, "sin", &program::rpn_sin, "sinus" },
{ cmd_keyword, "asin", &program::rpn_asin, "arg sinus" },
{ cmd_keyword, "cos", &program::rpn_cos , "cosinus" },
{ cmd_keyword, "acos", &program::rpn_acos, "arg cosinus" },
{ cmd_keyword, "tan", &program::rpn_tan, "tangent" },
{ cmd_keyword, "atan", &program::rpn_atan, "arg tangent" },
{ cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians" },
{ cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees" },
// TRIG ON REALS AND COMPLEXES
{cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
{cmd_keyword, "pi", &program::rpn_pi, "pi constant"},
{cmd_keyword, "sin", &program::rpn_sin, "sinus"},
{cmd_keyword, "asin", &program::rpn_asin, "arg sinus"},
{cmd_keyword, "cos", &program::rpn_cos, "cosinus"},
{cmd_keyword, "acos", &program::rpn_acos, "arg cosinus"},
{cmd_keyword, "tan", &program::rpn_tan, "tangent"},
{cmd_keyword, "atan", &program::rpn_atan, "arg tangent"},
{cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
{cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
//LOGS ON REALS AND COMPLEXES
{ cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
{ cmd_keyword, "e", &program::rpn_e, "Euler constant" },
{ cmd_keyword, "ln", &program::rpn_ln, "logarithm base e" },
{ 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, "exp", &program::rpn_exp, "exponential" },
{ cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0" },
{ cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10" },
{ cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10" },
{ cmd_keyword, "exp10", &program::rpn_alog10, "" },
{ cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2" },
{ cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2" },
{ cmd_keyword, "exp2", &program::rpn_alog2, "" },
{ cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine" },
{ cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine" },
{ cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine" },
{ 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" },
// LOGS ON REALS AND COMPLEXES
{cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
{cmd_keyword, "e", &program::rpn_e, "Euler constant"},
{cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"},
{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, "exp", &program::rpn_exp, "exponential"},
{cmd_keyword, "expm", &program::rpn_expm,
"exp(x)-1 which is useful when x is close to 0"},
{cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"},
{cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"},
{cmd_keyword, "exp10", &program::rpn_alog10, ""},
{cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"},
{cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"},
{cmd_keyword, "exp2", &program::rpn_alog2, ""},
{cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
{cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
{cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine"},
{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
{ 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)
{
// myobj.arg1 = 'if' condition evaluation value
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
int rpn_if(branch& myobj) {
// myobj.arg1 = 'if' condition evaluation value
MIN_ARGUMENTS_RET(1, -(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)
myobj.arg1 = 1;
else
myobj.arg1 = 0;
(void)_stack->pop_back();
return -1;
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
myobj.arg1 = 1;
else
myobj.arg1 = 0;
(void)_stack->pop_back();
return -1;
}
int rpn_then(branch& myobj)
{
// myobj.arg1 = index of then + 1
// myobj.arg2 = index of else + 1 or end + 1
// myobj.arg3 = index of if
// if condition is true -> arg1 (= jump to then + 1)
// else -> arg2 (= jump to else + 1 or end + 1)
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
if (if_cmd->arg1 == 1)
return myobj.arg1;
else
return myobj.arg2;
int rpn_then(branch& myobj) {
// myobj.arg1 = index of then + 1
// myobj.arg2 = index of else + 1 or end + 1
// myobj.arg3 = index of if
// if condition is true -> arg1 (= jump to then + 1)
// else -> arg2 (= jump to else + 1 or end + 1)
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
if (if_cmd->arg1 == 1)
return myobj.arg1;
else
return myobj.arg2;
}
int rpn_else(branch& myobj)
{
// myobj.arg1 = index of else + 1
// myobj.arg2 = index of end + 1
// myobj.arg3 = index of if
// if condition was false -> arg1 (= jump to else + 1)
// if condition was true -> arg2 (= jump to end + 1)
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
if (if_cmd->arg1 == 1)
return myobj.arg2;
else
return myobj.arg1;
int rpn_else(branch& myobj) {
// myobj.arg1 = index of else + 1
// myobj.arg2 = index of end + 1
// myobj.arg3 = index of if
// if condition was false -> arg1 (= jump to else + 1)
// if condition was true -> arg2 (= jump to end + 1)
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
if (if_cmd->arg1 == 1)
return myobj.arg2;
else
return myobj.arg1;
}
int rpn_end(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);
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;
int rpn_end(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);
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;
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;
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_do(branch& myobj) {
// nothing
return -1;
}
int rpn_for(branch& myobj)
{
int ret;
int rpn_until(branch& myobj) {
// nothing
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);
//
void rpn_ift(void) {
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
// 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();
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);
// 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();
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);
}
// 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;
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;
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
{
// store symbol with first value
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
ret = myobj.arg1 + 1;
}
return ret;
return myobj.arg1 + 1;
}
}
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
// 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;
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);
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);
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());
// 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
return myobj.arg1 + 1;
// 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;
}
}
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
// 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;
}
return ret;
}

View file

@ -1,130 +1,146 @@
void rpn_re()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
void rpn_re() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
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();
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);
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()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
void rpn_im() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
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();
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);
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()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
void rpn_arg() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
// calc atan2(x/y)
complex* cplx = (complex*)_stack->pop_back();
number* num = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
// calc atan2(x/y)
complex* cplx = (complex*)_stack->pop_back();
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);
_calc_stack.pop_back();
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
_calc_stack.pop_back();
}
void rpn_conj()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
void rpn_conj() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
complex* cplx = (complex*)_stack->back();
CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
complex* cplx = (complex*)_stack->back();
CHECK_MPFR(
mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_r2c()
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, 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();
void rpn_r2c() {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
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);
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);
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()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
void rpn_c2r() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
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);
number* im = (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);
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, 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();
CHECK_MPFR(mpfr_set(re->_value.mpfr,
((complex*)_calc_stack.back())->re()->mpfr,
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()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
void rpn_r2p() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
rpn_dup();
rpn_dup();
rpn_arg();
rpn_dup();
rpn_dup();
rpn_arg();
complex* cplx = (complex*)_stack->get_obj(1);
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
_stack->pop_back();
rpn_swap();
rpn_abs();
cplx = (complex*)_stack->get_obj(1);
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
_stack->pop_back();
complex* cplx = (complex*)_stack->get_obj(1);
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd));
_stack->pop_back();
rpn_swap();
rpn_abs();
cplx = (complex*)_stack->get_obj(1);
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr,
floating_t::s_mpfr_rnd));
_stack->pop_back();
}
void rpn_p2r()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
void rpn_p2r() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_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();
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_calc_stack.allocate_back(number::calc_size(), cmd_number);
//calc cos(theta)
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));
// 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 rcos(theta)
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
// calc cos(theta)
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)
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 rcos(theta)
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->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));
// calc sin(theta)
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()
{
// nop
void rpn_nop() {
// nop
}
void rpn_good_bye()
{
ERR_CONTEXT(ret_good_bye);
}
void rpn_good_bye() { ERR_CONTEXT(ret_good_bye); }
void rpn_help()
{
// software name
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
void rpn_help() {
// software name
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
// description
printf("%s\n\n", description);
// description
printf("%s\n\n", description);
// syntax
printf("%s\n", syntax);
// syntax
printf("%s\n", syntax);
// keywords
unsigned int i = 0;
while(s_keywords[i].type != cmd_max)
{
if (s_keywords[i].comment.size() != 0)
{
// titles in bold
if (s_keywords[i].type==cmd_undef)
printf(ATTR_BOLD);
// 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++;
// keywords
unsigned int i = 0;
while (s_keywords[i].type != cmd_max) {
if (s_keywords[i].comment.size() != 0) {
// titles in bold
if (s_keywords[i].type == cmd_undef) printf(ATTR_BOLD);
// 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);
}
printf("\n");
i++;
}
printf("\n");
// show mode
printf("Current float mode is ");
switch(number::s_mode)
{
case number::std: printf("'std'"); break;
case number::fix: printf("'fix'"); break;
case number::sci: printf("'sci'"); break;
default: printf("unknown"); break;
// show mode
printf("Current float mode is ");
switch (number::s_mode) {
case number::std:
printf("'std'");
break;
case number::fix:
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);
// 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");
} else
ERR_CONTEXT(ret_out_of_range);
}
int base_digits_from_bit_precision(int base, int bit_precision)
{
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
}
void rpn_round() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
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);
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;
}
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);
}
}
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);
}
if (!done) ERR_CONTEXT(ret_out_of_range);
}

View file

@ -1,377 +1,337 @@
void rpn_e(void)
{
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
euler->_value = 1L;
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
void rpn_e(void) {
number* euler =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
euler->_value = 1L;
CHECK_MPFR(
mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
}
void rpn_log10()
{
MIN_ARGUMENTS(1);
void rpn_log10() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
//log10(z)=ln(z)/ln(10)
rpn_ln();
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
// log10(z)=ln(z)/ln(10)
rpn_ln();
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_div();
}
else
ERR_CONTEXT(ret_bad_operand_type);
number* ten =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_div();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_alog10()
{
MIN_ARGUMENTS(1);
void rpn_alog10() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_mul();
rpn_exp();
}
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
number* ten =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_mul();
rpn_exp();
}
}
void rpn_log2()
{
MIN_ARGUMENTS(1);
void rpn_log2() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
//log2(z)=ln(z)/ln(2)
rpn_ln();
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
// log2(z)=ln(z)/ln(2)
rpn_ln();
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_div();
}
else
ERR_CONTEXT(ret_bad_operand_type);
number* two =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_div();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_alog2()
{
MIN_ARGUMENTS(1);
void rpn_alog2() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_mul();
rpn_exp();
}
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
number* two =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
rpn_ln();
rpn_mul();
rpn_exp();
}
}
void rpn_ln()
{
MIN_ARGUMENTS(1);
void rpn_ln() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
number* left = (number*)_stack->back();
if (_stack->get_type(0) == cmd_number) {
number* left = (number*)_stack->back();
// x<0 -> ln(x) = ln(-x)+i*pi
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0)
{
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
_stack->pop_back();
left = (number*)_calc_stack.back();
// x<0 -> ln(x) = ln(-x)+i*pi
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) {
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
_stack->pop_back();
left = (number*)_calc_stack.back();
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
}
else
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
else if (_stack->get_type(0) == cmd_complex)
{
// 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);
complex* cplx =
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr,
floating_t::s_mpfr_rnd));
CHECK_MPFR(
mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
} else
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr,
floating_t::s_mpfr_rnd));
} else if (_stack->get_type(0) == cmd_complex) {
// 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* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
// 1. atan(x/y)
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
// 1. atan(x/y)
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
// 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(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_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));
// 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(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_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));
_calc_stack.pop_back();
}
else
ERR_CONTEXT(ret_bad_operand_type);
_calc_stack.pop_back();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_exp()
{
MIN_ARGUMENTS(1);
void rpn_exp() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
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_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_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_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_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(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back();
}
else
ERR_CONTEXT(ret_bad_operand_type);
_calc_stack.pop_back();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_expm()
{
MIN_ARGUMENTS(1);
void rpn_expm() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
//exp(x)-1
rpn_exp();
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
// exp(x)-1
rpn_exp();
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();
}
else
ERR_CONTEXT(ret_bad_operand_type);
number* one =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_minus();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_lnp1()
{
MIN_ARGUMENTS(1);
void rpn_lnp1() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
{
//ln(x+1)
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_plus();
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
// ln(x+1)
number* one =
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
rpn_plus();
rpn_ln();
}
else
ERR_CONTEXT(ret_bad_operand_type);
rpn_ln();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_sinh()
{
MIN_ARGUMENTS(1);
void rpn_sinh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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)
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* 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();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
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_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_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_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_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_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_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
}
else
ERR_CONTEXT(ret_bad_operand_type);
_calc_stack.pop_back(2);
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_asinh()
{
MIN_ARGUMENTS(1);
void rpn_asinh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
rpn_square();
number* 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_plus();
rpn_squareroot();
rpn_plus();
rpn_ln();
}
else
ERR_CONTEXT(ret_bad_operand_type);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
rpn_square();
number* 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_plus();
rpn_squareroot();
rpn_plus();
rpn_ln();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_cosh()
{
MIN_ARGUMENTS(1);
void rpn_cosh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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)
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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)
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* 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();
floating_t* re = ((complex*)_stack->get_obj(0))->re();
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_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_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_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_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_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_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
_calc_stack.pop_back(2);
}
else
ERR_CONTEXT(ret_bad_operand_type);
_calc_stack.pop_back(2);
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_acosh()
{
MIN_ARGUMENTS(1);
void rpn_acosh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
number* 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_plus();
rpn_dup();
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_minus();
rpn_mul();
rpn_squareroot();
rpn_plus();
rpn_ln();
}
else
ERR_CONTEXT(ret_bad_operand_type);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
number* 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_plus();
rpn_dup();
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_minus();
rpn_mul();
rpn_squareroot();
rpn_plus();
rpn_ln();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_tanh()
{
MIN_ARGUMENTS(1);
void rpn_tanh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
floating_t* x = ((complex*)_stack->get_obj(1))->re();
floating_t* y = ((complex*)_stack->get_obj(1))->im();
floating_t* x = ((complex*)_stack->get_obj(1))->re();
floating_t* y = ((complex*)_stack->get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(1))->re();
floating_t* im = ((complex*)_stack->get_obj(1))->im();
floating_t* re = ((complex*)_stack->get_obj(1))->re();
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_tan(im->mpfr, y->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_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_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));
rpn_div();
}
else
ERR_CONTEXT(ret_bad_operand_type);
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_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));
rpn_div();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_atanh()
{
MIN_ARGUMENTS(1);
void rpn_atanh() {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
number* 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_plus();
rpn_swap();
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_div();
rpn_ln();
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
rpn_mul();
}
else
ERR_CONTEXT(ret_bad_operand_type);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
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))
rpn_dup();
number* 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_plus();
rpn_swap();
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_div();
rpn_ln();
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
rpn_mul();
} else
ERR_CONTEXT(ret_bad_operand_type);
}

View file

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

View file

@ -1,327 +1,273 @@
//
void rpn_sto(void)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
void rpn_sto(void) {
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
string name(((symbol*)_stack->pop_back())->_value);
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back();
string name(((symbol*)_stack->pop_back())->_value);
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back();
}
//
void rpn_stoadd(void)
{
MIN_ARGUMENTS(2);
void rpn_stoadd(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_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;
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);
// mind the order of heaps
if (find_variable(variable, obj, size))
{
(void)_stack->pop_back();
stack::copy_and_push_back(obj, *_stack, size);
rpn_rcl();
if (_err == ret_ok) {
rpn_plus();
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
_stack->pop_back();
}
else
ERR_CONTEXT(ret_unknown_variable);
} 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_edit(void)
{
MIN_ARGUMENTS(1);
void rpn_stosub(void) {
MIN_ARGUMENTS(2);
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);
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
ERR_CONTEXT(ret_runtime_error);
} 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);
// 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
void auto_rcl(symbol* symb)
{
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)
{
void auto_rcl(symbol* symb) {
if (symb->_auto_eval) {
object* obj;
unsigned int size;
program* parent = _parent_prog;
string name;
string variable(symb->_value);
// 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");
}
// 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_clusr(void)
{
_heap->erase_all();
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;
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()
{
MIN_ARGUMENTS(1);
void rpn_instr() {
MIN_ARGUMENTS(1);
// stringify only if not already a string
if (_stack->get_type(0) != cmd_string)
{
// write the object in stack(0) in a string and remove this obj
FILE* tmp = tmpfile();
if (tmp != NULL)
{
((object*)_stack->pop_back())->show(tmp);
// stringify only if not already a string
if (_stack->get_type(0) != cmd_string) {
// write the object in stack(0) in a string and remove this obj
FILE* tmp = tmpfile();
if (tmp != NULL) {
((object*)_stack->pop_back())->show(tmp);
// reserve the correct size on stack
unsigned int str_size = (unsigned int)ftell(tmp);
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
str->_len = str_size;
// reserve the correct size on stack
unsigned int str_size = (unsigned int)ftell(tmp);
ostring* str = (ostring*)_stack->allocate_back(
str_size + 1 + sizeof(ostring), cmd_string);
str->_len = str_size;
// fill the obj
rewind(tmp);
if (fread(str->_value, str_size, 1, tmp) != 1)
ERR_CONTEXT(ret_runtime_error);
str->_value[str_size] = 0;
fclose(tmp);
}
else
ERR_CONTEXT(ret_runtime_error);
}
// fill the obj
rewind(tmp);
if (fread(str->_value, str_size, 1, tmp) != 1)
ERR_CONTEXT(ret_runtime_error);
str->_value[str_size] = 0;
fclose(tmp);
} else
ERR_CONTEXT(ret_runtime_error);
}
}
void rpn_strout()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
void rpn_strout() {
MIN_ARGUMENTS(1);
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
if (program::parse(entry.c_str(), prog) == ret_ok)
// run it
prog.run(*_stack, *_heap);
// make program from string in stack level 1
if (program::parse(entry.c_str(), prog) == ret_ok)
// run it
prog.run(*_stack, *_heap);
}
void rpn_chr()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
void rpn_chr() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// get arg as number % 256
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
if (the_chr<32 || the_chr>126)
the_chr = '.';
// get arg as number % 256
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr,
floating_t::s_mpfr_rnd);
if (the_chr < 32 || the_chr > 126) the_chr = '.';
// reserve the correct size on stack (1 char)
unsigned int str_size = 1;
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
// reserve the correct size on stack (1 char)
unsigned int str_size = 1;
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->_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;
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;
}
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)
{
// write stack in a string, each entry separated between commas
for (int i = 0; i < (int)stk.size(); i++)
{
FILE* tmp_file = tmpfile();
char* line = NULL;
size_t len;
void test_get_stack(string& stack_is, stack& stk) {
// write stack in a string, each entry separated between commas
for (int i = 0; i < (int)stk.size(); i++) {
FILE* tmp_file = tmpfile();
char* line = NULL;
size_t len;
if (i > 0)
stack_is += ", ";
if (i > 0) stack_is += ", ";
if (tmp_file != NULL)
{
((object*)stk.seq_obj(i))->show(tmp_file);
if (tmp_file != NULL) {
((object*)stk.seq_obj(i))->show(tmp_file);
// write stack in a tmp file
(void)rewind(tmp_file);
if (getline(&line, &len, tmp_file) >=0)
{
stack_is += line;
free(line);
}
(void)fclose(tmp_file);
}
else
ERR_CONTEXT(ret_runtime_error);
}
// write stack in a tmp file
(void)rewind(tmp_file);
if (getline(&line, &len, tmp_file) >= 0) {
stack_is += line;
free(line);
}
(void)fclose(tmp_file);
} else
ERR_CONTEXT(ret_runtime_error);
}
}
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);
if(tests_failed>0)
printf(FG_RED);
printf("%d failed", tests_failed);
if(tests_failed>0)
printf(COLOR_OFF);
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);
if (tests_failed > 0) printf(FG_RED);
printf("%d failed", tests_failed);
if (tests_failed > 0) printf(COLOR_OFF);
printf(" (%d steps: %d passed, ", steps, steps-steps_failed);
if(steps_failed>0)
printf(FG_RED);
printf("%d failed", steps_failed);
if(steps_failed>0)
printf(COLOR_OFF);
printf(")\n");
printf(" (%d steps: %d passed, ", steps, steps - steps_failed);
if (steps_failed > 0) printf(FG_RED);
printf("%d failed", steps_failed);
if (steps_failed > 0) printf(COLOR_OFF);
printf(")\n");
}
void rpn_test()
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
void rpn_test() {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
int total_tests=0;
int total_tests_failed=0;
int total_steps=0;
int total_steps_failed=0;
int total_tests = 0;
int total_tests_failed = 0;
int total_steps = 0;
int total_steps_failed = 0;
string test_filename = ((ostring*)_stack->pop_back())->_value;
printf("\nrpn version is %s\n", version);
test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed);
test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed);
string test_filename = ((ostring*)_stack->pop_back())->_value;
printf("\nrpn version is %s\n", version);
test(test_filename, total_tests, total_tests_failed, total_steps,
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)
{
const string stack_size("-> stack size should be ");
const string stack_value("-> stack should be ");
const string cmd_error("-> error should be ");
const string cmd_exit("exit test");
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_value("-> stack should be ");
const string cmd_error("-> error should be ");
const string cmd_exit("exit test");
ifstream test_file(test_filename.c_str());
int tests = 0;
int tests_failed = 0;
int steps = 0;
int steps_failed = 0;
ifstream test_file(test_filename.c_str());
int tests = 0;
int tests_failed = 0;
int steps = 0;
int steps_failed = 0;
if (test_file.is_open())
{
string test_title;
string entry;
ret_value ret;
stack stk;
heap hp;
bool failed = false;
bool is_first_step;
bool is_test_error_shown;
int last_err;
stringstream cerr_buffer;
streambuf* cerr_old_buffer;
if (test_file.is_open()) {
string test_title;
string entry;
ret_value ret;
stack stk;
heap hp;
bool failed = false;
bool is_first_step;
bool is_test_error_shown;
int last_err;
stringstream cerr_buffer;
streambuf* cerr_old_buffer;
// redirect cerr
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
// redirect cerr
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
while (!test_file.eof())
{
getline(test_file, entry);
while (!test_file.eof()) {
getline(test_file, entry);
if (entry.substr(0,8)=="#include")
test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed);
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
if (entry.substr(0, 8) == "#include")
test(entry.substr(9), total_tests, total_tests_failed, total_steps,
total_steps_failed);
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");
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
failed = false;
// cerr back
cerr.rdbuf(cerr_old_buffer);
// 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++;
// conclusion: show and keep for total
if (tests != 0)
{
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
// check current stack size
istringstream isub;
int size;
total_tests += tests;
total_tests_failed += tests_failed;
total_steps += steps;
total_steps_failed += steps_failed;
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();
}
}
}
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()
{
// _stack sould have 2 strings at level 1 and 2
// this function removes these 2 entries
ostring* right = (ostring*)_stack->pop_back();
ostring* left = (ostring*)_stack->pop_back();
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
int cmp_strings_on_stack_top() {
// _stack sould have 2 strings at level 1 and 2
// this function removes these 2 entries
ostring* right = (ostring*)_stack->pop_back();
ostring* left = (ostring*)_stack->pop_back();
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
}
void rpn_sup(void)
{
MIN_ARGUMENTS(2);
void rpn_sup(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_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();
// 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_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);
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);
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)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
void rpn_sup_eq(void) {
MIN_ARGUMENTS(2);
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();
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);
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);
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)
{
MIN_ARGUMENTS(2);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
ARG_MUST_BE_OF_TYPE(1, cmd_number);
void rpn_inf(void) {
MIN_ARGUMENTS(2);
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();
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);
}
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
mpfr_set_si(left->_value.mpfr, 1, 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);
}
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_not(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
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_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
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)
{
rpn_eq();
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();
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)
{
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
void rpn_pi(void) {
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
}
void rpn_d2r(void)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
void rpn_d2r(void) {
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
// add pi on stack
rpn_pi();
// add pi on stack
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;
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));
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
} else if (_stack->get_type(0) == cmd_complex) {
// 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)
{
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_number);
void rpn_asin(void) {
MIN_ARGUMENTS(1);
// add pi on stack
rpn_pi();
floating_t* pi = &((number*)_stack->pop_back())->_value;
if (_stack->get_type(0) == cmd_number) {
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));
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
} else if (_stack->get_type(0) == cmd_complex) {
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)
{
MIN_ARGUMENTS(1);
void rpn_cos(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
else if (_stack->get_type(0) == cmd_complex)
{
// 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();
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_cos(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)
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
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));
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();
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));
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
_calc_stack.pop_back(2);
}
else
ERR_CONTEXT(ret_bad_operand_type);
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));
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));
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)
{
MIN_ARGUMENTS(1);
void rpn_acos(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
else if (_stack->get_type(0) == cmd_complex)
{
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);
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
} else if (_stack->get_type(0) == cmd_complex) {
// acos(z)=pi/2-asin(z)
rpn_asin();
rpn_pi();
number* 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_div();
rpn_minus();
rpn_neg();
} else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_cos(void)
{
MIN_ARGUMENTS(1);
void rpn_tan(void) {
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_cos(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)
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();
if (_stack->get_type(0) == cmd_number) {
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_tan(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)
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
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));
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
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();
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));
floating_t* re = ((complex*)_stack->get_obj(0))->re();
floating_t* im = ((complex*)_stack->get_obj(0))->im();
_calc_stack.pop_back(2);
}
else
ERR_CONTEXT(ret_bad_operand_type);
// 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_acos(void)
{
MIN_ARGUMENTS(1);
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_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
else if (_stack->get_type(0) == cmd_complex)
{
//acos(z)=pi/2-asin(z)
rpn_asin();
rpn_pi();
number* 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_div();
rpn_minus();
rpn_neg();
}
else
ERR_CONTEXT(ret_bad_operand_type);
}
void rpn_tan(void)
{
MIN_ARGUMENTS(1);
if (_stack->get_type(0) == cmd_number)
{
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_tan(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)
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();
//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);
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;
// allocation base size
#define ALLOC_STACK_CHUNK (64*1024)
#define ALLOC_STACK_CHUNK (64 * 1024)
//
class stack
{
public:
stack()
{
_base = NULL;
_base_pointer = NULL;
_total_size = 0;
_total_count_pointer = 0;
erase();
class stack {
public:
stack() {
_base = NULL;
_base_pointer = NULL;
_total_size = 0;
_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()
{
if (_base != NULL)
free(_base);
if (_base_pointer != NULL)
free(_base_pointer);
// manage pointers memory allocation (add one page if needed)
if ((_count + 1) > _total_count_pointer) {
_base_pointer = (object**)realloc(
_base_pointer,
(_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
}
void erase()
{
_current = _base;
_count = 0;
// recalc object pointers in case of base reallocation
if (data_is_reallocated) {
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();
}
}
//
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));
// manage stack itself
_base_pointer[_count++] = (object*)_current;
allocated = (object*)_current;
_current += size;
if (allocated->_type == cmd_number)
((number*)allocated)->move();
else if (allocated->_type == cmd_complex)
((complex*)allocated)->move();
// init object
allocated->_type = type;
allocated->_size = size;
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;
}
}
//
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);
return back;
}
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;
unsigned int size() { return _count; }
// 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;
// stack access (stack_level=0=first out)
object* get_obj(unsigned int stack_level) {
return seq_obj(_count - stack_level - 1);
}
old_base = _base;
_base = (char*)realloc(_base, _total_size);
object* operator[](unsigned int stack_level) {
return seq_obj(_count - stack_level - 1);
}
_current = _base + (_current - old_base);
data_is_reallocated = true;
}
object* back() {
object* obj = NULL;
if (_count > 0) obj = _base_pointer[_count - 1];
return obj;
}
// manage pointers memory allocation (add one page if needed)
if ((_count + 1) > _total_count_pointer)
{
_base_pointer = (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
}
unsigned int get_len(unsigned int index) {
return seq_len(_count - index - 1);
}
// recalc object pointers in case of base reallocation
if (data_is_reallocated)
{
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();
}
}
cmd_type_t get_type(unsigned int index) {
return seq_type(_count - index - 1);
}
// manage stack itself
_base_pointer[_count++] = (object*)_current;
allocated = (object*)_current;
_current += size;
// 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;
}
// init object
allocated->_type = type;
allocated->_size = size;
if (type == cmd_number)
((number*)allocated)->init();
else if (type == cmd_complex)
((complex*)allocated)->init();
unsigned int seq_len(unsigned int index) {
unsigned int len = 0;
if (index < _count) len = _base_pointer[index]->_size;
return len;
}
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)
{
object* back = NULL;
private:
char* _base;
char* _current;
object** _base_pointer;
// pop several entries, return the last
while (pop_count-- > 0)
{
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
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
{
public:
heap() { }
virtual ~heap() { }
class heap : public stack {
public:
heap() {}
virtual ~heap() {}
object* add(const string name, object* obj, unsigned int size)
{
map<string, unsigned int>::iterator i = _map.find(name);
object* local = NULL;
object* add(const string name, object* obj, unsigned int size) {
map<string, unsigned int>::iterator i = _map.find(name);
object* local = NULL;
// variable does not exist in heap or already exists but its size is too short -> allocate
if (i!=_map.end())
local = seq_obj(i->second);
// variable does not exist in heap or already exists but its size is too
// short -> allocate
if (i != _map.end()) local = seq_obj(i->second);
if (local==NULL || (local!=NULL && size>local->_size))
{
copy_and_push_back(obj, *this, size);
_map[name] = ((stack*)this)->size()-1;
}
else
{
// variable already exists in heap but previous was larger -> don't reallocate
// copy a whole stack entry and push it back to another stack
memcpy(local, obj, size);
if (local->_type == cmd_number)
((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;
if (local == NULL || (local != NULL && size > local->_size)) {
copy_and_push_back(obj, *this, size);
_map[name] = ((stack*)this)->size() - 1;
} else {
// variable already exists in heap but previous was larger -> don't
// reallocate copy a whole stack entry and push it back to another stack
memcpy(local, obj, size);
if (local->_type == cmd_number)
((number*)local)->move();
else if (local->_type == cmd_complex)
((complex*)local)->move();
}
bool replace_value(const string name, object* obj, unsigned int size)
{
bool ret=false;
map<string, unsigned int>::iterator i = _map.find(name);
return local;
}
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(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 exist(const string name)
{
return (_map.find(name) != _map.end());
bool replace_value(const string name, object* obj, unsigned int size) {
bool ret = false;
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)
{
if (num>=0 && num<(int)_map.size())
{
object* local;
map<string, unsigned int>::iterator i= _map.begin();
bool exist(const string name) { return (_map.find(name) != _map.end()); }
for(int j = 0; j < num; j++)
i++;
bool get_by_index(int num, string& name, object*& obj, unsigned int& size) {
if (num >= 0 && num < (int)_map.size()) {
object* local;
map<string, unsigned int>::iterator i = _map.begin();
local = (object*)seq_obj(i->second);
name = i->first;
obj = local;
size = local->_size;
return true;
}
else
return false;
for (int j = 0; j < num; j++) i++;
local = (object*)seq_obj(i->second);
name = i->first;
obj = local;
size = local->_size;
return true;
} 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)
{
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;
}
void erase_all(void)
{
// map
_map.erase(_map.begin(), _map.end());
void erase_all(void) {
// map
_map.erase(_map.begin(), _map.end());
// and stack
((stack*)this)->erase();
}
// and stack
((stack*)this)->erase();
}
unsigned int count_vars() { return _map.size(); }
unsigned int count_vars() { return _map.size(); }
private:
map<string, unsigned int> _map;
private:
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"
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";
// syntax
static const char syntax[] =
ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\n"
"with optional command = list of commands";
ATTR_BOLD "Syntax" ATTR_OFF
": rpn [command]\n"
"with optional command = list of commands";