From abe2bd12e84e3bb3cf3ca09fab40b995813b899c Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 12 Aug 2018 11:50:49 +0200 Subject: [PATCH] #210: google-styled code --- src/.clang-format | 1 + src/constant.h | 66 ++- src/debug.h | 133 +++-- src/main.cpp | 234 ++++---- src/object.cpp | 383 ++++++------- src/object.hpp | 482 +++++++--------- src/parse.hpp | 1055 ++++++++++++++++------------------- src/program.cpp | 402 ++++++++------ src/program.hpp | 1009 ++++++++++++++++----------------- src/rpn-branch.hpp | 514 ++++++++--------- src/rpn-complex.hpp | 212 +++---- src/rpn-general.hpp | 409 +++++++------- src/rpn-logs.hpp | 570 +++++++++---------- src/rpn-program.hpp | 256 ++++----- src/rpn-real.hpp | 1231 +++++++++++++++++++++-------------------- src/rpn-stack.hpp | 277 +++++----- src/rpn-store.hpp | 558 +++++++++---------- src/rpn-string.hpp | 264 +++++---- src/rpn-test-core.hpp | 424 +++++++------- src/rpn-test.hpp | 469 ++++++++-------- src/rpn-trig.hpp | 444 +++++++-------- src/stack.hpp | 513 ++++++++--------- src/version.h | 7 +- 23 files changed, 4729 insertions(+), 5184 deletions(-) create mode 100644 src/.clang-format diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 0000000..f6cb8ad --- /dev/null +++ b/src/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/constant.h b/src/constant.h index 1203276..c90de55 100644 --- a/src/constant.h +++ b/src/constant.h @@ -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) diff --git a/src/debug.h b/src/debug.h index 6431dc4..9dc8f15 100644 --- a/src/debug.h +++ b/src/debug.h @@ -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 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 diff --git a/src/main.cpp b/src/main.cpp index fd1f0dd..899bb6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,12 @@ // std c -#include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include // 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 #include +#include 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, ""); - 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, ""); + 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, ""); - } - 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, ""); + } + 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; + } } diff --git a/src/object.hpp b/src/object.hpp index a4bfc68..125f460 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -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 diff --git a/src/parse.hpp b/src/parse.hpp index 6bb0234..9745660 100644 --- a/src/parse.hpp +++ b/src/parse.hpp @@ -1,618 +1,545 @@ public: -static ret_value parse(const char* entry, program& prog) -{ - vector entries; - ret_value ret = ret_ok; +static ret_value parse(const char* entry, program& prog) { + vector entries; + ret_value ret = ret_ok; - //1. cut global entry string into shorter strings - if (_cut(entry, entries)) - { - //2. make an object from each entry, and add it to the program - for (vector::iterator it = entries.begin(); it != entries.end(); it++) - { - string remaining_entry; - string main_entry = (*it); - while(main_entry.size()>0) - { - // remaining_entry is used only in case of concatenated entry - // ex: entry="1 2+" -> vector = {"1", "2+"} -> first "1", second "2" and remaining_entry="+" - // this remaining entry is treated as an entry + // 1. cut global entry string into shorter strings + if (_cut(entry, entries)) { + // 2. make an object from each entry, and add it to the program + for (vector::iterator it = entries.begin(); it != entries.end(); + it++) { + string remaining_entry; + string main_entry = (*it); + while (main_entry.size() > 0) { + // remaining_entry is used only in case of concatenated entry + // ex: entry="1 2+" -> vector = {"1", "2+"} -> first "1", + // second "2" and remaining_entry="+" this remaining entry is treated as + // an entry - // TODO errors ? - _obj_from_string(main_entry, prog, remaining_entry); - main_entry = remaining_entry; - } - } + // TODO errors ? + _obj_from_string(main_entry, prog, remaining_entry); + main_entry = remaining_entry; + } } + } - return ret; + return ret; } // interactive entry and decoding -static ret_value entry(program& prog) -{ - string entry_str; - char* entry; - int entry_len; - int total_entry_len; - ret_value ret = ret_max; - bool multiline = false; +static ret_value entry(program& prog) { + string entry_str; + char* entry; + int entry_len; + int total_entry_len; + ret_value ret = ret_max; + bool multiline = false; - // linenoise for entry - linenoiseSetCompletionCallback(program::entry_completion_generator); + // linenoise for entry + linenoiseSetCompletionCallback(program::entry_completion_generator); - while(ret == ret_max) - { - // get user entry - if (multiline) - entry = linenoise(MULTILINE_PROMPT, &entry_len); - else - entry = linenoise(PROMPT, &entry_len); + while (ret == ret_max) { + // get user entry + if (multiline) + entry = linenoise(MULTILINE_PROMPT, &entry_len); + else + entry = linenoise(PROMPT, &entry_len); - // Ctrl-C - if (linenoiseKeyType() == 1) - { - if (entry_len > 0 || multiline) - ret = ret_abort_current_entry; - else - ret = ret_good_bye; - } - else if (linenoiseKeyType() == 3) - { - multiline = true; - if (entry != NULL) - entry_str += entry; - entry_str += " "; - } - else - { - if (entry != NULL) - { - entry_str += entry; + // Ctrl-C + if (linenoiseKeyType() == 1) { + if (entry_len > 0 || multiline) + ret = ret_abort_current_entry; + else + ret = ret_good_bye; + } else if (linenoiseKeyType() == 3) { + multiline = true; + if (entry != NULL) entry_str += entry; + entry_str += " "; + } else { + if (entry != NULL) { + entry_str += entry; - // parse it - ret = parse(entry_str.c_str(), prog); + // parse it + ret = parse(entry_str.c_str(), prog); - // keep history - if (entry[0] != 0) - linenoiseHistoryAdd(entry_str.c_str()); - } - else - ret = ret_internal; - } - - free(entry); + // keep history + if (entry[0] != 0) linenoiseHistoryAdd(entry_str.c_str()); + } else + ret = ret_internal; } - return ret; + free(entry); + } + + return ret; } private: -static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type) -{ - unsigned int i = 0; - while(s_keywords[i].type != cmd_max) - { - if (strncasecmp(fn_name, s_keywords[i].name, sizeof(s_keywords[i].name)) == 0) - { - fn = s_keywords[i].fn; - type = s_keywords[i].type; - return ret_ok; - } - i++; +static ret_value get_fn(const char* fn_name, program_fn_t& fn, + cmd_type_t& type) { + unsigned int i = 0; + while (s_keywords[i].type != cmd_max) { + if (strncasecmp(fn_name, s_keywords[i].name, sizeof(s_keywords[i].name)) == + 0) { + fn = s_keywords[i].fn; + type = s_keywords[i].type; + return ret_ok; } - return ret_unknown_err; + i++; + } + return ret_unknown_err; } -static bool _cut(const char* entry, vector& entries) -{ - string tmp; - int len = strlen(entry); +static bool _cut(const char* entry, vector& entries) { + string tmp; + int len = strlen(entry); - for (int i=0; i < len; i++) - { - switch(entry[i]) - { - //symbol - case '\'': - //push prec entry if exists - if (tmp.size() > 0) - { - entries.push_back(tmp); - tmp.clear(); - } - //get symbol - tmp='\''; - i++; - while((i < len) && entry[i]!='\'') - tmp += entry[i++]; - if ((i < len) && entry[i] != '\'') - tmp += '\''; - entries.push_back(tmp); - tmp.clear(); - break; - - //string - case '"': - //push prec entry if exists - if (tmp.size() > 0) - { - entries.push_back(tmp); - tmp.clear(); - } - //get expression - tmp='"'; - i++; - while(i < len && entry[i]!='"') - tmp += entry[i++]; - - if ((i < len) && entry[i] != '"') - tmp += '"'; - - entries.push_back(tmp); - tmp.clear(); - break; - - //program - case '<': - //push prec entry if exists - if (tmp.size()>0) - { - entries.push_back(tmp); - tmp.clear(); - } - - if (strncmp(&entry[i], "<<", 2) == 0) - { - int up = 1; - - // found a program begin - i += 2; - tmp = "<< "; - - // trim leading spaces - while (i < len && isspace(entry[i])) - i++; - - while(i < len) - { - if (strncmp(&entry[i], "<<", 2) == 0) - { - up++; - i += 2; - tmp += "<< "; - // trim leading spaces - while (i < len && isspace(entry[i])) - i++; - } - else if (strncmp(&entry[i], ">>", 2) == 0) - { - if (isspace(entry[i-1]) && entry[i-2]!='>') - tmp += ">>"; - else - tmp += " >>"; - - up--; - i += 2; - - // trim trailing spaces - while (i < len && isspace(entry[i])) - i++; - - // found end - if (up == 0) - break; - } - else - { - tmp += entry[i]; - i++; - } - } - while((up--)>0) - tmp += " >>"; - - if (tmp.size()>0) - { - entries.push_back(tmp); - tmp.clear(); - } - i--;// i has move 1 too far - } - else - // reinject '<'' which is not a prog begin - tmp = "<"; - break; - - //complex - case '(': - //push prec entry if exists - if (tmp.size() > 0) - { - entries.push_back(tmp); - tmp.clear(); - } - //get complex - while((i < len) && entry[i]!=')') - tmp += entry[i++]; - if ((i < len) && entry[i] != ')') - tmp += ')'; - if (tmp.size()>0) - { - entries.push_back(tmp); - tmp.clear(); - } - break; - - //other - default: - if (!isspace(entry[i])) - tmp += entry[i]; - else - { - if (tmp.size()>0) - { - entries.push_back(tmp); - tmp.clear(); - } - } - break; + for (int i = 0; i < len; i++) { + switch (entry[i]) { + // symbol + case '\'': + // push prec entry if exists + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); } - } - if (tmp.size()>0) - { + // get symbol + tmp = '\''; + i++; + while ((i < len) && entry[i] != '\'') tmp += entry[i++]; + if ((i < len) && entry[i] != '\'') tmp += '\''; entries.push_back(tmp); tmp.clear(); - } - return entries.size()>0; -} + break; -static bool get_keyword(const string& entry, program& prog, string& remaining_entry) -{ - program_fn_t fn; - unsigned int obj_len; - cmd_type_t type; - bool ret = false; - - // could be a command - if (get_fn(entry.c_str(), fn, type) == ret_ok) - { - if (type == cmd_keyword) - { - // allocate keyword object - obj_len = sizeof(keyword)+entry.size()+1; - keyword* new_obj = (keyword*)prog.allocate_back(obj_len, cmd_keyword); - new_obj->set(fn, entry.c_str(), entry.size()); - ret = true; + // string + case '"': + // push prec entry if exists + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); } - else if (type == cmd_branch) - { - // allocate branch object - obj_len = sizeof(branch)+entry.size()+1; - branch* new_obj = (branch*)prog.allocate_back(obj_len, cmd_branch); - new_obj->set((branch_fn_t)fn, entry.c_str(), entry.size()); - ret = true; + // get expression + tmp = '"'; + i++; + while (i < len && entry[i] != '"') tmp += entry[i++]; + + if ((i < len) && entry[i] != '"') tmp += '"'; + + entries.push_back(tmp); + tmp.clear(); + break; + + // program + case '<': + // push prec entry if exists + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); } - } - return ret; -} + if (strncmp(&entry[i], "<<", 2) == 0) { + int up = 1; -static bool get_symbol(const string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; - int entry_len = entry.size(); - unsigned int obj_len; + // found a program begin + i += 2; + tmp = "<< "; - if (entry_len>=1 && entry[0]=='\'') - { - if (entry_len == 1) - { - // void symbol entry, like ' - // total object length - obj_len = sizeof(symbol)+1; + // trim leading spaces + while (i < len && isspace(entry[i])) i++; - // allocate and set object - // symbol beginning with ' is not autoevaluated - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set("", 0, false); - } - else - { - // symbol entry, like 'toto' or 'toto - int naked_entry_len; + while (i < len) { + if (strncmp(&entry[i], "<<", 2) == 0) { + up++; + i += 2; + tmp += "<< "; + // trim leading spaces + while (i < len && isspace(entry[i])) i++; + } else if (strncmp(&entry[i], ">>", 2) == 0) { + if (isspace(entry[i - 1]) && entry[i - 2] != '>') + tmp += ">>"; + else + tmp += " >>"; - // entry length without prefix / postfix - naked_entry_len = entry[entry_len-1]=='\''?(entry_len-2):(entry_len-1); - // total object length - obj_len = sizeof(symbol)+naked_entry_len+1; + up--; + i += 2; - // allocate and set object - // symbol beginning with ' is not autoevaluated - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len, false); - } - ret = true; - } + // trim trailing spaces + while (i < len && isspace(entry[i])) i++; - return ret; -} - -static bool get_other(const string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; - int entry_len = entry.size(); - unsigned int obj_len; - - if (entry_len>=1) - { - // entry which is nothing is considered as an auto-evaluated symbol - int naked_entry_len; - - // entry length without prefix / postfix - naked_entry_len = entry[entry_len-1]=='\''?(entry_len-1):(entry_len); - // total object length - obj_len = sizeof(symbol)+naked_entry_len+1; - - // allocate and set object - // symbol not beginning with ' is autoevaluated (ie is evaluated when pushed on stack) - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set(entry.c_str(), naked_entry_len, true); - ret = true; - } - - return ret; -} - -static bool get_string(const string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len>=1 && entry[0]=='"') - { - if (entry_len == 1) - { - // total object length - obj_len = sizeof(ostring)+1; - - // allocate and set object - ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); - new_obj->set("", 0); - } - else - { - int naked_entry_len; - - // entry length without prefix / postfix - naked_entry_len = entry[entry_len-1]=='"'?(entry_len-2):(entry_len-1); - - // total object length - obj_len = sizeof(ostring)+naked_entry_len+1; - - // allocate and set object - ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); - new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len); - } - ret = true; - } - - return ret; -} - -static bool get_program(string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len>=2 && entry[0]=='<' && entry[1]=='<') - { - int naked_entry_len; - - // entry length without prefix / postfix - if (entry_len>=4 && entry[entry_len-1]=='>' && entry[entry_len-2]=='>') - naked_entry_len = entry_len-4; - else - naked_entry_len = entry_len-2; - - // total object length - obj_len = sizeof(oprogram)+naked_entry_len+1; - - // allocate and set object - oprogram* new_obj = (oprogram*)prog.allocate_back(obj_len, cmd_program); - new_obj->set(&entry[2], naked_entry_len); - - ret = true; - } - return ret; -} - -static bool get_number(string& entry, program& prog, string& remaining_entry) -{ - char* endptr; - bool ret = false; - - if (entry.size() > 0) - { - // pre parse to avoid doing a useless allocation - // detect the begining of a number including nan, inf, @nan@, @inf@ - if (entry.find_first_of("+-0123456789.ni@", 0) == 0) - { - // detect an arbitrary base entry like 3bXXX or 27bYYY - int base = 0; - size_t base_detect = entry.find_first_of("b", 0); - if (base_detect == 1 || base_detect == 2) - if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62) - entry=entry.substr(base_detect+1); - else - base = 0; - - number* num = (number*)prog.allocate_back(number::calc_size(), cmd_number); - - int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, base, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != entry.c_str()) - { - // determine representation - if (base != 0) - { - num->_representation = number::base; - num->_base = base; - } - else - { - string beg = entry.substr(0, 2); - if (beg == "0x" || beg == "0X") - num->_representation = number::hex; - else if (beg == "0b" || beg == "0B") - num->_representation = number::bin; - else - num->_representation = number::dec; - } - - ret = true; - - // remaining string if any - remaining_entry = endptr; + // found end + if (up == 0) break; + } else { + tmp += entry[i]; + i++; } - else - (void)prog.pop_back(); + } + while ((up--) > 0) tmp += " >>"; + + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); + } + i--; // i has move 1 too far + } else + // reinject '<'' which is not a prog begin + tmp = "<"; + break; + + // complex + case '(': + // push prec entry if exists + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); } - } - - return ret; -} - -static bool get_complex(const string& entry, program& prog, string& remaining_entry) -{ - char* endptr; - bool ret = false; - - if (entry.size() > 0) - { - size_t comma = entry.find(','); - if (comma != string::npos) - { - complex* cplx; - - // pre parse RE to avoid doing a useless allocation - // detect the begining of a number, including nan, inf, @nan@, @inf@ - string re_str = entry.substr(1, comma-1).c_str(); - if (re_str.find_first_of(" +-0123456789.ni@", 0) == 0) - { - cplx = (complex*)prog.allocate_back(complex::calc_size(), cmd_complex); - - int mpfr_ret = mpfr_strtofr(cplx->re()->mpfr, re_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != re_str.c_str()) - { - // determine representation - string beg = re_str.substr(0, 2); - if (beg == "0x" || beg == "0X") - cplx->_representation = complex::hex; - else - cplx->_representation = complex::dec; - - ret = true; - } - else - (void)prog.pop_back(); - } - - // pre parse IM to avoid doing a useless allocation - // detect the begining of a number, including nan, inf, @nan@, @inf@ - string im_str = entry.substr(comma+1).c_str(); - if (ret == true && im_str.find_first_of(" +-0123456789.ni@", 0) == 0) - { - ret = false; - int mpfr_ret = mpfr_strtofr(cplx->im()->mpfr, im_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != im_str.c_str()) - { - // determine representation - string beg = im_str.substr(0, 2); - if (beg == "0x" || beg == "0X") - cplx->_representation = complex::hex; - else - cplx->_representation = complex::dec; - - ret = true; - } - else - (void)prog.pop_back(); - } + // get complex + while ((i < len) && entry[i] != ')') tmp += entry[i++]; + if ((i < len) && entry[i] != ')') tmp += ')'; + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); } - } + break; - return ret; + // other + default: + if (!isspace(entry[i])) + tmp += entry[i]; + else { + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); + } + } + break; + } + } + if (tmp.size() > 0) { + entries.push_back(tmp); + tmp.clear(); + } + return entries.size() > 0; } -static bool get_comment(string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len>=1 && entry[0]=='#') - { - // entry (complete line) is ignored - ret = true; +static bool get_keyword(const string& entry, program& prog, + string& remaining_entry) { + program_fn_t fn; + unsigned int obj_len; + cmd_type_t type; + bool ret = false; + + // could be a command + if (get_fn(entry.c_str(), fn, type) == ret_ok) { + if (type == cmd_keyword) { + // allocate keyword object + obj_len = sizeof(keyword) + entry.size() + 1; + keyword* new_obj = (keyword*)prog.allocate_back(obj_len, cmd_keyword); + new_obj->set(fn, entry.c_str(), entry.size()); + ret = true; + } else if (type == cmd_branch) { + // allocate branch object + obj_len = sizeof(branch) + entry.size() + 1; + branch* new_obj = (branch*)prog.allocate_back(obj_len, cmd_branch); + new_obj->set((branch_fn_t)fn, entry.c_str(), entry.size()); + ret = true; } - return ret; + } + + return ret; } -static bool _obj_from_string(string& entry, program& prog, string& remaining_entry) -{ - bool ret = false; +static bool get_symbol(const string& entry, program& prog, + string& remaining_entry) { + bool ret = false; + int entry_len = entry.size(); + unsigned int obj_len; - remaining_entry.erase(); + if (entry_len >= 1 && entry[0] == '\'') { + if (entry_len == 1) { + // void symbol entry, like ' + // total object length + obj_len = sizeof(symbol) + 1; - if (get_number(entry, prog, remaining_entry)) - ret = true; - else if (get_symbol(entry, prog, remaining_entry)) - ret = true; - else if (get_string(entry, prog, remaining_entry)) - ret = true; - else if (get_program(entry, prog, remaining_entry)) - ret = true; - else if (get_keyword(entry, prog, remaining_entry)) - ret = true; - else if (get_complex(entry, prog, remaining_entry)) - ret = true; - else if (get_comment(entry, prog, remaining_entry)) - ret = true; + // allocate and set object + // symbol beginning with ' is not autoevaluated + symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); + new_obj->set("", 0, false); + } else { + // symbol entry, like 'toto' or 'toto + int naked_entry_len; + + // entry length without prefix / postfix + naked_entry_len = + entry[entry_len - 1] == '\'' ? (entry_len - 2) : (entry_len - 1); + // total object length + obj_len = sizeof(symbol) + naked_entry_len + 1; + + // allocate and set object + // symbol beginning with ' is not autoevaluated + symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); + new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len, + false); + } + ret = true; + } + + return ret; +} + +static bool get_other(const string& entry, program& prog, + string& remaining_entry) { + bool ret = false; + int entry_len = entry.size(); + unsigned int obj_len; + + if (entry_len >= 1) { + // entry which is nothing is considered as an auto-evaluated symbol + int naked_entry_len; + + // entry length without prefix / postfix + naked_entry_len = + entry[entry_len - 1] == '\'' ? (entry_len - 1) : (entry_len); + // total object length + obj_len = sizeof(symbol) + naked_entry_len + 1; + + // allocate and set object + // symbol not beginning with ' is autoevaluated (ie is evaluated when pushed + // on stack) + symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); + new_obj->set(entry.c_str(), naked_entry_len, true); + ret = true; + } + + return ret; +} + +static bool get_string(const string& entry, program& prog, + string& remaining_entry) { + bool ret = false; + unsigned int obj_len; + int entry_len = entry.size(); + if (entry_len >= 1 && entry[0] == '"') { + if (entry_len == 1) { + // total object length + obj_len = sizeof(ostring) + 1; + + // allocate and set object + ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); + new_obj->set("", 0); + } else { + int naked_entry_len; + + // entry length without prefix / postfix + naked_entry_len = + entry[entry_len - 1] == '"' ? (entry_len - 2) : (entry_len - 1); + + // total object length + obj_len = sizeof(ostring) + naked_entry_len + 1; + + // allocate and set object + ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); + new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len); + } + ret = true; + } + + return ret; +} + +static bool get_program(string& entry, program& prog, string& remaining_entry) { + bool ret = false; + unsigned int obj_len; + int entry_len = entry.size(); + if (entry_len >= 2 && entry[0] == '<' && entry[1] == '<') { + int naked_entry_len; + + // entry length without prefix / postfix + if (entry_len >= 4 && entry[entry_len - 1] == '>' && + entry[entry_len - 2] == '>') + naked_entry_len = entry_len - 4; else - // nothing, considered as an auto-evaluated symbol - if (get_other(entry, prog, remaining_entry)) - ret = true; + naked_entry_len = entry_len - 2; - return ret; + // total object length + obj_len = sizeof(oprogram) + naked_entry_len + 1; + + // allocate and set object + oprogram* new_obj = (oprogram*)prog.allocate_back(obj_len, cmd_program); + new_obj->set(&entry[2], naked_entry_len); + + ret = true; + } + return ret; } -static void entry_completion_generator(const char* text, linenoiseCompletions* lc) -{ - int i = 0; - int text_len = strnlen(text, 6); +static bool get_number(string& entry, program& prog, string& remaining_entry) { + char* endptr; + bool ret = false; - // propose all keywords - if (text_len ==0) - { - while(s_keywords[i].type != cmd_max) - { - if (s_keywords[i].fn != NULL) - // add all keywords - linenoiseAddCompletion(lc, s_keywords[i].name); - i++; - } - } - // propose keywords matching to text begining - else - { - while(s_keywords[i].type != cmd_max) - { - if (s_keywords[i].fn != NULL) - { - // compare list entry with text, return if match - if (strncmp(s_keywords[i].name, text, text_len) == 0) - linenoiseAddCompletion(lc, s_keywords[i].name); - } - i++; + if (entry.size() > 0) { + // pre parse to avoid doing a useless allocation + // detect the begining of a number including nan, inf, @nan@, @inf@ + if (entry.find_first_of("+-0123456789.ni@", 0) == 0) { + // detect an arbitrary base entry like 3bXXX or 27bYYY + int base = 0; + size_t base_detect = entry.find_first_of("b", 0); + if (base_detect == 1 || base_detect == 2) + if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62) + entry = entry.substr(base_detect + 1); + else + base = 0; + + number* num = + (number*)prog.allocate_back(number::calc_size(), cmd_number); + + int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, + base, MPFR_DEFAULT_RND); + if (endptr != NULL && endptr != entry.c_str()) { + // determine representation + if (base != 0) { + num->_representation = number::base; + num->_base = base; + } else { + string beg = entry.substr(0, 2); + if (beg == "0x" || beg == "0X") + num->_representation = number::hex; + else if (beg == "0b" || beg == "0B") + num->_representation = number::bin; + else + num->_representation = number::dec; } + + ret = true; + + // remaining string if any + remaining_entry = endptr; + } else + (void)prog.pop_back(); } + } + + return ret; +} + +static bool get_complex(const string& entry, program& prog, + string& remaining_entry) { + char* endptr; + bool ret = false; + + if (entry.size() > 0) { + size_t comma = entry.find(','); + if (comma != string::npos) { + complex* cplx; + + // pre parse RE to avoid doing a useless allocation + // detect the begining of a number, including nan, inf, @nan@, @inf@ + string re_str = entry.substr(1, comma - 1).c_str(); + if (re_str.find_first_of(" +-0123456789.ni@", 0) == 0) { + cplx = (complex*)prog.allocate_back(complex::calc_size(), cmd_complex); + + int mpfr_ret = mpfr_strtofr(cplx->re()->mpfr, re_str.c_str(), &endptr, + 0, MPFR_DEFAULT_RND); + if (endptr != NULL && endptr != re_str.c_str()) { + // determine representation + string beg = re_str.substr(0, 2); + if (beg == "0x" || beg == "0X") + cplx->_representation = complex::hex; + else + cplx->_representation = complex::dec; + + ret = true; + } else + (void)prog.pop_back(); + } + + // pre parse IM to avoid doing a useless allocation + // detect the begining of a number, including nan, inf, @nan@, @inf@ + string im_str = entry.substr(comma + 1).c_str(); + if (ret == true && im_str.find_first_of(" +-0123456789.ni@", 0) == 0) { + ret = false; + int mpfr_ret = mpfr_strtofr(cplx->im()->mpfr, im_str.c_str(), &endptr, + 0, MPFR_DEFAULT_RND); + if (endptr != NULL && endptr != im_str.c_str()) { + // determine representation + string beg = im_str.substr(0, 2); + if (beg == "0x" || beg == "0X") + cplx->_representation = complex::hex; + else + cplx->_representation = complex::dec; + + ret = true; + } else + (void)prog.pop_back(); + } + } + } + + return ret; +} + +static bool get_comment(string& entry, program& prog, string& remaining_entry) { + bool ret = false; + unsigned int obj_len; + int entry_len = entry.size(); + if (entry_len >= 1 && entry[0] == '#') { + // entry (complete line) is ignored + ret = true; + } + return ret; +} + +static bool _obj_from_string(string& entry, program& prog, + string& remaining_entry) { + bool ret = false; + + remaining_entry.erase(); + + if (get_number(entry, prog, remaining_entry)) + ret = true; + else if (get_symbol(entry, prog, remaining_entry)) + ret = true; + else if (get_string(entry, prog, remaining_entry)) + ret = true; + else if (get_program(entry, prog, remaining_entry)) + ret = true; + else if (get_keyword(entry, prog, remaining_entry)) + ret = true; + else if (get_complex(entry, prog, remaining_entry)) + ret = true; + else if (get_comment(entry, prog, remaining_entry)) + ret = true; + else + // nothing, considered as an auto-evaluated symbol + if (get_other(entry, prog, remaining_entry)) + ret = true; + + return ret; +} + +static void entry_completion_generator(const char* text, + linenoiseCompletions* lc) { + int i = 0; + int text_len = strnlen(text, 6); + + // propose all keywords + if (text_len == 0) { + while (s_keywords[i].type != cmd_max) { + if (s_keywords[i].fn != NULL) + // add all keywords + linenoiseAddCompletion(lc, s_keywords[i].name); + i++; + } + } + // propose keywords matching to text begining + else { + while (s_keywords[i].type != cmd_max) { + if (s_keywords[i].fn != NULL) { + // compare list entry with text, return if match + if (strncmp(s_keywords[i].name, text, text_len) == 0) + linenoiseAddCompletion(lc, s_keywords[i].name); + } + i++; + } + } } diff --git a/src/program.cpp b/src/program.cpp index e3ab77e..78b5384 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -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 then else 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 next| step" }, - { cmd_branch, "for", (program_fn_t)&program::rpn_for, " for next| 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, ift" }, - { cmd_keyword, "ifte",&program::rpn_ifte, "similar to if-then-else-end, ifte" }, - { cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until 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 repeat 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 then else " + "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 next| step"}, + {cmd_branch, "for", (program_fn_t)&program::rpn_for, + " for next| 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, ift"}, + {cmd_keyword, "ifte", &program::rpn_ifte, + "similar to if-then-else-end, " + " ifte"}, + {cmd_branch, "do", (program_fn_t)&program::rpn_do, + "do until 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 repeat 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, ""}, }; diff --git a/src/program.hpp b/src/program.hpp index 7689c61..4c1817f 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -2,22 +2,22 @@ #define PROGRAM_HPP // std c -#include -#include -#include #include +#include +#include +#include extern "C" { -#include #include +#include } // std c++ -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace std; // external libs @@ -26,584 +26,539 @@ using namespace std; // internal includes #include "constant.h" -#include "escape.h" -#include "version.h" #include "debug.h" +#include "escape.h" #include "object.hpp" #include "stack.hpp" +#include "version.h" // -struct if_layout_t -{ - if_layout_t():index_then_or_unti_or_repeat(-1),index_else(-1),index_end(-1),is_do_unti(false),is_while_repeat(false) { } - int index_if_or_do_or_while; - int index_then_or_unti_or_repeat; - int index_else; - int index_end; - bool is_do_unti; - bool is_while_repeat; +struct if_layout_t { + if_layout_t() + : index_then_or_unti_or_repeat(-1), + index_else(-1), + index_end(-1), + is_do_unti(false), + is_while_repeat(false) {} + int index_if_or_do_or_while; + int index_then_or_unti_or_repeat; + int index_else; + int index_end; + bool is_do_unti; + bool is_while_repeat; }; // program -class program : public stack -{ -public: - program(program* parent_prog = NULL) { _parent_prog = parent_prog; interrupt_now = false; } +class program : public stack { + public: + program(program* parent_prog = NULL) { + _parent_prog = parent_prog; + interrupt_now = false; + } - // run this program - ret_value run(stack& stk, heap& hp) - { - bool go_out = false; - ret_value ret = ret_ok; - cmd_type_t type; + // run this program + ret_value run(stack& stk, heap& hp) { + bool go_out = false; + ret_value ret = ret_ok; + cmd_type_t type; - // stack comes from outside - _stack = &stk; + // stack comes from outside + _stack = &stk; - // global heap comes from outside - _heap = &hp; + // global heap comes from outside + _heap = &hp; - _err = ret_ok; - _err_context = ""; + _err = ret_ok; + _err_context = ""; - // branches for 'if' - ret = preprocess(); - if (ret != ret_ok) - return ret; + // branches for 'if' + ret = preprocess(); + if (ret != ret_ok) return ret; - // iterate commands - for(int i = 0; (go_out==false) && (interrupt_now==false) && (i<(int)size());) - { - type = (cmd_type_t)seq_type(i); + // iterate commands + for (int i = 0; + (go_out == false) && (interrupt_now == false) && (i < (int)size());) { + type = (cmd_type_t)seq_type(i); - // could be an auto-evaluated symbol - if (type == cmd_symbol) - { - auto_rcl((symbol*)seq_obj(i)); - i++; - } - - // a keyword - else if (type == cmd_keyword) - { - keyword* k = (keyword*)seq_obj(i); - // call matching function - (this->*(k->_fn))(); - switch(_err) - { - // no pb -> go on - case ret_ok: - break; - // explicit go out software - case ret_good_bye: - go_out = true; - ret = ret_good_bye; - break; - default: - // error: abort prog - go_out = true; - - // error: show it - if (show_error(_err, _err_context) == ret_deadly) - { - // pb showing error -> go out software - ret = ret_good_bye; - } - break; - } - i++; - } - - // a branch keyword - else if (type == cmd_branch) - { - // call matching function - branch* b = (branch*)seq_obj(i); - int next_cmd = (this->*(b->_fn))(*b); - switch (next_cmd) - { - case -1: - i++; // meaning 'next command' - break; - case -(int)ret_runtime_error: - // error: show it - (void)show_error(_err, _err_context); - go_out = true;// end of run - break; - default: - i = next_cmd;// new direction - break; - } - } - - // not a command, but a stack entry, manage it - else - { - // copy the program stack entry to the running stack - stack::copy_and_push_back(*this, i, stk); - i++; + // could be an auto-evaluated symbol + if (type == cmd_symbol) { + auto_rcl((symbol*)seq_obj(i)); + i++; + } + + // a keyword + else if (type == cmd_keyword) { + keyword* k = (keyword*)seq_obj(i); + // call matching function + (this->*(k->_fn))(); + switch (_err) { + // no pb -> go on + case ret_ok: + break; + // explicit go out software + case ret_good_bye: + go_out = true; + ret = ret_good_bye; + break; + default: + // error: abort prog + go_out = true; + + // error: show it + if (show_error(_err, _err_context) == ret_deadly) { + // pb showing error -> go out software + ret = ret_good_bye; } + break; } - - if (interrupt_now) - { - fprintf(stderr, "\nInterrupted\n"); - interrupt_now = false; + i++; + } + + // a branch keyword + else if (type == cmd_branch) { + // call matching function + branch* b = (branch*)seq_obj(i); + int next_cmd = (this->*(b->_fn))(*b); + switch (next_cmd) { + case -1: + i++; // meaning 'next command' + break; + case -(int)ret_runtime_error: + // error: show it + (void)show_error(_err, _err_context); + go_out = true; // end of run + break; + default: + i = next_cmd; // new direction + break; } + } - return ret; - } - - void stop() - { - interrupt_now = true; + // not a command, but a stack entry, manage it + else { + // copy the program stack entry to the running stack + stack::copy_and_push_back(*this, i, stk); + i++; + } } - bool compare_keyword(keyword* k, const char* str_to_compare, int len) - { - if (k->_len >= len) - return strncmp(k->_value, str_to_compare, len) == 0; - else - return false; + if (interrupt_now) { + fprintf(stderr, "\nInterrupted\n"); + interrupt_now = false; } - bool compare_branch(branch* b, const char* str_to_compare, int len) - { - if (b->_len >= len) - return strncasecmp(b->_value, str_to_compare, len) == 0; - else - return false; - } + return ret; + } - ret_value preprocess(void) - { - // for if-then-else-end - vector vlayout; - int layout_index=-1; - // for start-end-step - vector vstartindex; + void stop() { interrupt_now = true; } - // analyse if-then-else-end branches - // analyse start-{next, step} branches - for(int i=0; i<(int)size(); i++) - { - int type = seq_type(i); - if (type == cmd_branch) - { - branch* k = (branch*)seq_obj(i); - if (compare_branch(k, "if", 2)) - { - if_layout_t layout; - layout.index_if_or_do_or_while = i; - vlayout.push_back(layout); - layout_index++; - } - else if (compare_branch(k, "then", 4)) - { - int next = i + 1; - if (next >= (int)size()) - next = -1; + bool compare_keyword(keyword* k, const char* str_to_compare, int len) { + if (k->_len >= len) + return strncmp(k->_value, str_to_compare, len) == 0; + else + return false; + } - // nothing after 'then' -> error - if (next == -1) - { - // error: show it - show_syntax_error("missing end after then"); - return ret_syntax; - } - if (layout_index<0) - { - // error: show it - show_syntax_error("missing if before then"); - return ret_syntax; - } - if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - { - // error: show it - show_syntax_error("duplicate then"); - return ret_syntax; - } - vlayout[layout_index].index_then_or_unti_or_repeat = i; - k->arg1 = next; - k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - } - else if (compare_branch(k, "else", 4)) - { - int next = i + 1; - if (next >= (int)size()) - next = -1; + bool compare_branch(branch* b, const char* str_to_compare, int len) { + if (b->_len >= len) + return strncasecmp(b->_value, str_to_compare, len) == 0; + else + return false; + } - // nothing after 'else' -> error - if (next == -1) - { - // error: show it - show_syntax_error("missing end after else"); - return ret_syntax; - } - if (layout_index<0) - { - // error: show it - show_syntax_error("missing if before else"); - return ret_syntax; - } - if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) - { - // error: show it - show_syntax_error("missing then before else"); - return ret_syntax; - } - if (vlayout[layout_index].index_else != -1) - { - // error: show it - show_syntax_error("duplicate else"); - return ret_syntax; - } - vlayout[layout_index].index_else = i; - k->arg1 = next;// fill branch1 (if was false) of 'else' - k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = next;// fill branch2 (if was false) of 'then' - } - else if (compare_branch(k, "start", 5)) - vstartindex.push_back(i); - else if (compare_branch(k, "for", 3)) - { - vstartindex.push_back(i); - k->arg1 = i + 1;// arg1 points on symbol variable - } - else if(compare_branch(k, "next", 4)) - { - if (vstartindex.size() == 0) - { - // error: show it - show_syntax_error("missing start or for before next"); - return ret_syntax; - } - k->arg1 = vstartindex[vstartindex.size() - 1]; // 'next' arg1 = 'start' index - ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index - vstartindex.pop_back(); - } - else if (compare_branch(k, "step", 4)) - { - if (vstartindex.size() == 0) - { - // error: show it - show_syntax_error("missing start or for before step"); - return ret_syntax; - } - k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index - ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index - vstartindex.pop_back(); - } - else if (compare_branch(k, "->", 2)) - { - k->arg1 = i;// arg1 is '->' command index in program - } - else if (compare_branch(k, "do", 2)) - { - if_layout_t layout; - layout.index_if_or_do_or_while = i; - layout.is_do_unti = true; - vlayout.push_back(layout); - layout_index++; - } - else if (compare_branch(k, "until", 4)) - { - int next = i + 1; - if (next >= (int)size()) - next = -1; + ret_value preprocess(void) { + // for if-then-else-end + vector vlayout; + int layout_index = -1; + // for start-end-step + vector vstartindex; - // nothing after 'unti' -> error - if (next == -1) - { - // error: show it - show_syntax_error("missing end"); - return ret_syntax; - } - if (layout_index<0 || !vlayout[layout_index].is_do_unti) - { - // error: show it - show_syntax_error("missing do"); - return ret_syntax; - } - if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - { - // error: show it - show_syntax_error("duplicate until"); - return ret_syntax; - } - vlayout[layout_index].index_then_or_unti_or_repeat = i; - } - else if (compare_branch(k, "while", 4)) - { - if_layout_t layout; - layout.index_if_or_do_or_while = i; - layout.is_while_repeat = true; - vlayout.push_back(layout); - layout_index++; - } - else if (compare_branch(k, "repeat", 5)) - { - if (layout_index<0 || !vlayout[layout_index].is_while_repeat) - { - // error: show it - show_syntax_error("missing while"); - return ret_syntax; - } - if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - { - // error: show it - show_syntax_error("duplicate repeat"); - return ret_syntax; - } - vlayout[layout_index].index_then_or_unti_or_repeat = i; - } - else if (compare_branch(k, "end", 3)) - { - int next = i + 1; - if (next >= (int)size()) - next = -1; + // analyse if-then-else-end branches + // analyse start-{next, step} branches + for (int i = 0; i < (int)size(); i++) { + int type = seq_type(i); + if (type == cmd_branch) { + branch* k = (branch*)seq_obj(i); + if (compare_branch(k, "if", 2)) { + if_layout_t layout; + layout.index_if_or_do_or_while = i; + vlayout.push_back(layout); + layout_index++; + } else if (compare_branch(k, "then", 4)) { + int next = i + 1; + if (next >= (int)size()) next = -1; - if (layout_index<0) - { - // error: show it - show_syntax_error("missing branch instruction before end"); - return ret_syntax; - } - else - { - if (vlayout[layout_index].is_do_unti) - { - // this end closes a do..unti - if (vlayout[layout_index].index_end != -1) - { - // error: show it - show_syntax_error("duplicate end"); - return ret_syntax; - } + // nothing after 'then' -> error + if (next == -1) { + // error: show it + show_syntax_error("missing end after then"); + return ret_syntax; + } + if (layout_index < 0) { + // error: show it + show_syntax_error("missing if before then"); + return ret_syntax; + } + if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { + // error: show it + show_syntax_error("duplicate then"); + return ret_syntax; + } + vlayout[layout_index].index_then_or_unti_or_repeat = i; + k->arg1 = next; + k->arg3 = vlayout[layout_index].index_if_or_do_or_while; + } else if (compare_branch(k, "else", 4)) { + int next = i + 1; + if (next >= (int)size()) next = -1; - if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) - { - // error: show it - show_syntax_error("missing until"); - return ret_syntax; - } + // nothing after 'else' -> error + if (next == -1) { + // error: show it + show_syntax_error("missing end after else"); + return ret_syntax; + } + if (layout_index < 0) { + // error: show it + show_syntax_error("missing if before else"); + return ret_syntax; + } + if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { + // error: show it + show_syntax_error("missing then before else"); + return ret_syntax; + } + if (vlayout[layout_index].index_else != -1) { + // error: show it + show_syntax_error("duplicate else"); + return ret_syntax; + } + vlayout[layout_index].index_else = i; + k->arg1 = next; // fill branch1 (if was false) of 'else' + k->arg3 = vlayout[layout_index].index_if_or_do_or_while; + ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat)) + ->arg2 = next; // fill branch2 (if was false) of 'then' + } else if (compare_branch(k, "start", 5)) + vstartindex.push_back(i); + else if (compare_branch(k, "for", 3)) { + vstartindex.push_back(i); + k->arg1 = i + 1; // arg1 points on symbol variable + } else if (compare_branch(k, "next", 4)) { + if (vstartindex.size() == 0) { + // error: show it + show_syntax_error("missing start or for before next"); + return ret_syntax; + } + k->arg1 = vstartindex[vstartindex.size() - + 1]; // 'next' arg1 = 'start' index + ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = + i; // 'for' or 'start' arg2 = 'next' index + vstartindex.pop_back(); + } else if (compare_branch(k, "step", 4)) { + if (vstartindex.size() == 0) { + // error: show it + show_syntax_error("missing start or for before step"); + return ret_syntax; + } + k->arg1 = vstartindex[vstartindex.size() - + 1]; // fill 'step' branch1 = 'start' index + ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = + i; // 'for' or 'start' arg2 = 'next' index + vstartindex.pop_back(); + } else if (compare_branch(k, "->", 2)) { + k->arg1 = i; // arg1 is '->' command index in program + } else if (compare_branch(k, "do", 2)) { + if_layout_t layout; + layout.index_if_or_do_or_while = i; + layout.is_do_unti = true; + vlayout.push_back(layout); + layout_index++; + } else if (compare_branch(k, "until", 4)) { + int next = i + 1; + if (next >= (int)size()) next = -1; - k->arg1 = vlayout[layout_index].index_if_or_do_or_while + 1; - layout_index--; - } - else if (vlayout[layout_index].is_while_repeat) - { - // this end closes a while..repeat - if (vlayout[layout_index].index_end != -1) - { - // error: show it - show_syntax_error("duplicate end"); - return ret_syntax; - } - - k->arg2 = vlayout[layout_index].index_if_or_do_or_while + 1; - - if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) - { - // error: show it - show_syntax_error("missing repeat"); - return ret_syntax; - } - - //fill 'repeat' arg1 with 'end+1' - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg1 = i + 1; - layout_index--; - } - else - { - // this end closes an if..then..(else) - if (vlayout[layout_index].index_end != -1) - { - // error: show it - show_syntax_error("duplicate end"); - return ret_syntax; - } - if (vlayout[layout_index].index_else != -1) - //fill 'end' branch of 'else' - ((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i; - else - { - //fill 'end' branch of 'then' - if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = i; - else - { - // error: show it - show_syntax_error("missing then"); - return ret_syntax; - } - } - layout_index--; - } - } - } - } - } - if (layout_index >= 0) - { + // nothing after 'unti' -> error + if (next == -1) { // error: show it show_syntax_error("missing end"); return ret_syntax; - } - if (vstartindex.size() > 0) - { + } + if (layout_index < 0 || !vlayout[layout_index].is_do_unti) { // error: show it - show_syntax_error("missing next or step after for or start"); + show_syntax_error("missing do"); return ret_syntax; - } - return ret_ok; - } + } + if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { + // error: show it + show_syntax_error("duplicate until"); + return ret_syntax; + } + vlayout[layout_index].index_then_or_unti_or_repeat = i; + } else if (compare_branch(k, "while", 4)) { + if_layout_t layout; + layout.index_if_or_do_or_while = i; + layout.is_while_repeat = true; + vlayout.push_back(layout); + layout_index++; + } else if (compare_branch(k, "repeat", 5)) { + if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) { + // error: show it + show_syntax_error("missing while"); + return ret_syntax; + } + if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { + // error: show it + show_syntax_error("duplicate repeat"); + return ret_syntax; + } + vlayout[layout_index].index_then_or_unti_or_repeat = i; + } else if (compare_branch(k, "end", 3)) { + int next = i + 1; + if (next >= (int)size()) next = -1; - ret_value show_error() - { - ret_value ret; + if (layout_index < 0) { + // error: show it + show_syntax_error("missing branch instruction before end"); + return ret_syntax; + } else { + if (vlayout[layout_index].is_do_unti) { + // this end closes a do..unti + if (vlayout[layout_index].index_end != -1) { + // error: show it + show_syntax_error("duplicate end"); + return ret_syntax; + } - // show last recorded error - cerr<<_err_context<<": error "<<_err<<": "<arg1 = vlayout[layout_index].index_if_or_do_or_while + 1; + layout_index--; + } else if (vlayout[layout_index].is_while_repeat) { + // this end closes a while..repeat + if (vlayout[layout_index].index_end != -1) { + // error: show it + show_syntax_error("duplicate end"); + return ret_syntax; + } - ret_value show_error(ret_value err, const char* context) - { - // record error - _err = err; - _err_context = context; - return show_error(); - } + k->arg2 = vlayout[layout_index].index_if_or_do_or_while + 1; - void show_syntax_error(const char* context) - { - // record error - _err = ret_syntax; - _err_context = context; - (void)show_error(); - } + if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { + // error: show it + show_syntax_error("missing repeat"); + return ret_syntax; + } - ret_value get_err(void) { return _err; } - - static void show_stack(stack& st, bool show_separator = true) - { - if (st.size() == 1) - { - ((object*)st.back())->show(); - printf("\n"); - } - else - { - for (int i = st.size()-1; i>=0; i--) - { - if (show_separator) - printf("%d%s", i+1, SHOW_STACK_SEPARATOR); - ((object*)st[i])->show(); - printf("\n"); + // fill 'repeat' arg1 with 'end+1' + ((branch*)seq_obj( + vlayout[layout_index].index_then_or_unti_or_repeat)) + ->arg1 = i + 1; + layout_index--; + } else { + // this end closes an if..then..(else) + if (vlayout[layout_index].index_end != -1) { + // error: show it + show_syntax_error("duplicate end"); + return ret_syntax; + } + if (vlayout[layout_index].index_else != -1) + // fill 'end' branch of 'else' + ((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i; + else { + // fill 'end' branch of 'then' + if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) + ((branch*)seq_obj( + vlayout[layout_index].index_then_or_unti_or_repeat)) + ->arg2 = i; + else { + // error: show it + show_syntax_error("missing then"); + return ret_syntax; + } + } + layout_index--; } + } } + } } - - static void apply_default() - { - //default float precision, float mode - number::s_mode = DEFAULT_MODE; - number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; + if (layout_index >= 0) { + // error: show it + show_syntax_error("missing end"); + return ret_syntax; + } + if (vstartindex.size() > 0) { + // error: show it + show_syntax_error("missing next or step after for or start"); + return ret_syntax; + } + return ret_ok; + } - // format for mpfr_printf - stringstream ss; - ss << number::s_decimal_digits; - number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD); + ret_value show_error() { + ret_value ret; - // default calc precision for MPFR - floating_t::s_mpfr_prec = (mpfr_prec_t)MPFR_DEFAULT_PREC_BITS; - floating_t::s_mpfr_prec_bytes = MPFR_DEFAULT_STORING_LENGTH_BYTES; + // show last recorded error + cerr << _err_context << ": error " << _err << ": " + << s_ret_value_string[_err] << endl; + switch (_err) { + case ret_internal: + case ret_deadly: + ret = ret_deadly; + default: + ret = ret_ok; } -private: - - bool interrupt_now; - - // current error and its context - ret_value _err; - string _err_context; + return ret; + } - // global stack holding results for user - stack* _stack; + ret_value show_error(ret_value err, string& context) { + // record error + _err = err; + _err_context = context; + return show_error(); + } - // global heap (sto, rcl) - heap* _heap; + ret_value show_error(ret_value err, const char* context) { + // record error + _err = err; + _err_context = context; + return show_error(); + } - // local heap for local loop variables (for..next) - heap _local_heap; + void show_syntax_error(const char* context) { + // record error + _err = ret_syntax; + _err_context = context; + (void)show_error(); + } - // calc stack internally used by branch and calc commands - stack _calc_stack; + ret_value get_err(void) { return _err; } - // parent prog for inheriting heaps - program* _parent_prog; - - int stack_size() - { - return _stack->size(); + static void show_stack(stack& st, bool show_separator = true) { + if (st.size() == 1) { + ((object*)st.back())->show(); + printf("\n"); + } else { + for (int i = st.size() - 1; i >= 0; i--) { + if (show_separator) printf("%d%s", i + 1, SHOW_STACK_SEPARATOR); + ((object*)st[i])->show(); + printf("\n"); + } } - -private: - static const char* s_ret_value_string[ret_max]; + } - // carefull : some of these macros modify program flow - #define ERR_CONTEXT(err) do { _err = (err); _err_context = __FUNCTION__; } while(0) - #define MIN_ARGUMENTS(num) do { if (stack_size()<(num)) { ERR_CONTEXT(ret_missing_operand); return; } } while(0) - #define MIN_ARGUMENTS_RET(num, ret) do { if (stack_size()<(num)) { ERR_CONTEXT(ret_missing_operand); return (ret); } } while(0) - #define ARG_MUST_BE_OF_TYPE(num, type) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } } while(0) - #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } } while(0) - #define IS_ARG_TYPE(num, type) (_stack->get_type(num) == (type)) - #define CHECK_MPFR(op) do { (void)(op); } while(0) + static void apply_default() { + // default float precision, float mode + number::s_mode = DEFAULT_MODE; + number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; - // keywords - struct keyword_t - { - cmd_type_t type; - char name[MAX_COMMAND_LENGTH]; - program_fn_t fn; - string comment; - }; - static keyword_t s_keywords[]; + // format for mpfr_printf + stringstream ss; + ss << number::s_decimal_digits; + number::s_mpfr_printf_format = + string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD); - // keywords implementation - #include "rpn-general.hpp" - #include "rpn-real.hpp" - #include "rpn-complex.hpp" - #include "rpn-test.hpp" - #include "rpn-stack.hpp" - #include "rpn-string.hpp" - #include "rpn-branch.hpp" - #include "rpn-store.hpp" - #include "rpn-program.hpp" - #include "rpn-trig.hpp" - #include "rpn-logs.hpp" - #include "rpn-test-core.hpp" + // default calc precision for MPFR + floating_t::s_mpfr_prec = (mpfr_prec_t)MPFR_DEFAULT_PREC_BITS; + floating_t::s_mpfr_prec_bytes = MPFR_DEFAULT_STORING_LENGTH_BYTES; + } - // parser - #include "parse.hpp" + private: + bool interrupt_now; + + // current error and its context + ret_value _err; + string _err_context; + + // global stack holding results for user + stack* _stack; + + // global heap (sto, rcl) + heap* _heap; + + // local heap for local loop variables (for..next) + heap _local_heap; + + // calc stack internally used by branch and calc commands + stack _calc_stack; + + // parent prog for inheriting heaps + program* _parent_prog; + + int stack_size() { return _stack->size(); } + + private: + static const char* s_ret_value_string[ret_max]; + +// carefull : some of these macros modify program flow +#define ERR_CONTEXT(err) \ + do { \ + _err = (err); \ + _err_context = __FUNCTION__; \ + } while (0) +#define MIN_ARGUMENTS(num) \ + do { \ + if (stack_size() < (num)) { \ + ERR_CONTEXT(ret_missing_operand); \ + return; \ + } \ + } while (0) +#define MIN_ARGUMENTS_RET(num, ret) \ + do { \ + if (stack_size() < (num)) { \ + ERR_CONTEXT(ret_missing_operand); \ + return (ret); \ + } \ + } while (0) +#define ARG_MUST_BE_OF_TYPE(num, type) \ + do { \ + if (_stack->get_type(num) != (type)) { \ + ERR_CONTEXT(ret_bad_operand_type); \ + return; \ + } \ + } while (0) +#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ + do { \ + if (_stack->get_type(num) != (type)) { \ + ERR_CONTEXT(ret_bad_operand_type); \ + return (ret); \ + } \ + } while (0) +#define IS_ARG_TYPE(num, type) (_stack->get_type(num) == (type)) +#define CHECK_MPFR(op) \ + do { \ + (void)(op); \ + } while (0) + + // keywords + struct keyword_t { + cmd_type_t type; + char name[MAX_COMMAND_LENGTH]; + program_fn_t fn; + string comment; + }; + static keyword_t s_keywords[]; + +// keywords implementation +#include "rpn-branch.hpp" +#include "rpn-complex.hpp" +#include "rpn-general.hpp" +#include "rpn-logs.hpp" +#include "rpn-program.hpp" +#include "rpn-real.hpp" +#include "rpn-stack.hpp" +#include "rpn-store.hpp" +#include "rpn-string.hpp" +#include "rpn-test-core.hpp" +#include "rpn-test.hpp" +#include "rpn-trig.hpp" + +// parser +#include "parse.hpp" }; #endif diff --git a/src/rpn-branch.hpp b/src/rpn-branch.hpp index 5b93bfc..a99c32b 100644 --- a/src/rpn-branch.hpp +++ b/src/rpn-branch.hpp @@ -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; } diff --git a/src/rpn-complex.hpp b/src/rpn-complex.hpp index 6a36248..875e7ec 100644 --- a/src/rpn-complex.hpp +++ b/src/rpn-complex.hpp @@ -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)); } diff --git a/src/rpn-general.hpp b/src/rpn-general.hpp index af95fe0..254fdce 100644 --- a/src/rpn-general.hpp +++ b/src/rpn-general.hpp @@ -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<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); } diff --git a/src/rpn-logs.hpp b/src/rpn-logs.hpp index 2df7766..1c9a218 100644 --- a/src/rpn-logs.hpp +++ b/src/rpn-logs.hpp @@ -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); } diff --git a/src/rpn-program.hpp b/src/rpn-program.hpp index 3e36af4..bdd2bde 100644 --- a/src/rpn-program.hpp +++ b/src/rpn-program.hpp @@ -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 + // -> ... + + // 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 - // -> ... - - // 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; + } - // is missing - if (! prog_found) - { - ERR_CONTEXT(ret_syntax); - show_error(_err, context); - return -1; - } + // 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; } diff --git a/src/rpn-real.hpp b/src/rpn-real.hpp index 9743379..4468e05 100644 --- a/src/rpn-real.hpp +++ b/src/rpn-real.hpp @@ -1,677 +1,692 @@ -void rpn_plus() -{ - MIN_ARGUMENTS(2); +void rpn_plus() { + MIN_ARGUMENTS(2); - // adding strings - if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) - { - unsigned int left_str_size = ((ostring*)_stack->get_obj(1))->_len; - unsigned int right_str_size = ((ostring*)_stack->get_obj(0))->_len; + // adding strings + if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { + unsigned int left_str_size = ((ostring*)_stack->get_obj(1))->_len; + unsigned int right_str_size = ((ostring*)_stack->get_obj(0))->_len; - 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(); - (void)_stack->pop_back(); + 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(); + (void)_stack->pop_back(); - ostring* str = (ostring*)_stack->allocate_back(left_str_size+right_str_size+1+sizeof(ostring), cmd_string); - str->_len = left_str_size+right_str_size; + ostring* str = (ostring*)_stack->allocate_back( + left_str_size + right_str_size + 1 + sizeof(ostring), cmd_string); + str->_len = left_str_size + right_str_size; - strncpy(str->_value, ((ostring*)_calc_stack.get_obj(1))->_value, left_str_size); - strncat(str->_value, ((ostring*)_calc_stack.get_obj(0))->_value, right_str_size); - _calc_stack.pop_back(); - _calc_stack.pop_back(); - } - // adding numbers - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) - { - number* right = (number*)_stack->pop_back(); - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // adding complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) - { - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - } - // adding complex+number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) - { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // adding number+complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) - { - rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else - ERR_CONTEXT(ret_bad_operand_type); + strncpy(str->_value, ((ostring*)_calc_stack.get_obj(1))->_value, + left_str_size); + strncat(str->_value, ((ostring*)_calc_stack.get_obj(0))->_value, + right_str_size); + _calc_stack.pop_back(); + _calc_stack.pop_back(); + } + // adding numbers + else if (_stack->get_type(0) == cmd_number && + _stack->get_type(1) == cmd_number) { + number* right = (number*)_stack->pop_back(); + number* left = (number*)_stack->back(); + CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, + right->_value.mpfr, floating_t::s_mpfr_rnd)); + } + // adding complexes + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_complex) { + complex* right = (complex*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, + floating_t::s_mpfr_rnd)); + } + // adding complex+number + else if (_stack->get_type(0) == cmd_number && + _stack->get_type(1) == cmd_complex) { + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } + // adding number+complex + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_number) { + rpn_swap(); + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } else + ERR_CONTEXT(ret_bad_operand_type); } -void rpn_minus() -{ - MIN_ARGUMENTS(2); +void rpn_minus() { + MIN_ARGUMENTS(2); - // substracting 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(); - CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // substracting complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) - { - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - } - // substracting complex-number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) - { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // substracting number-complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) - { - rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, right->_value.mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); - } - else - ERR_CONTEXT(ret_bad_operand_type); + // substracting 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(); + CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, + right->_value.mpfr, floating_t::s_mpfr_rnd)); + } + // substracting complexes + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_complex) { + complex* right = (complex*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, + floating_t::s_mpfr_rnd)); + } + // substracting complex-number + else if (_stack->get_type(0) == cmd_number && + _stack->get_type(1) == cmd_complex) { + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } + // substracting number-complex + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_number) { + rpn_swap(); + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_sub(left->re()->mpfr, right->_value.mpfr, left->re()->mpfr, + floating_t::s_mpfr_rnd)); + } else + ERR_CONTEXT(ret_bad_operand_type); } -void rpn_mul() -{ - MIN_ARGUMENTS(2); +void rpn_mul() { + MIN_ARGUMENTS(2); - // multiplying 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(); - CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // multiplying complexes (a+ib)*(x+iy)=(ax-by)+i(ay+bx)=a(x+iy)+b(-y+ix) - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) - { - complex* right = (complex*)_stack->pop_back();//x+iy - complex* left = (complex*)_stack->back();//a+ib + // multiplying 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(); + CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, + right->_value.mpfr, floating_t::s_mpfr_rnd)); + } + // multiplying complexes (a+ib)*(x+iy)=(ax-by)+i(ay+bx)=a(x+iy)+b(-y+ix) + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_complex) { + complex* right = (complex*)_stack->pop_back(); // x+iy + complex* left = (complex*)_stack->back(); // a+ib - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); - complex* left_sav = (complex*)_calc_stack.back();//a+ib + stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + complex* left_sav = (complex*)_calc_stack.back(); // a+ib - // left: (a+ib)->(ax+iay) - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->re()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - - // right: (x+iy)-> (bx-iby) - CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_neg(right->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); + // left: (a+ib)->(ax+iay) + CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->re()->mpfr, + right->im()->mpfr, floating_t::s_mpfr_rnd)); - //left=left+transpose(right) - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); + // right: (x+iy)-> (bx-iby) + CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->im()->mpfr, + right->im()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR( + mpfr_neg(right->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, + right->re()->mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(); - } - // multiplying complex*number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) - { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // multiplying number*complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) - { - rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else - ERR_CONTEXT(ret_bad_operand_type); + // left=left+transpose(right) + CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->im()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); + + _calc_stack.pop_back(); + } + // multiplying complex*number + else if (_stack->get_type(0) == cmd_number && + _stack->get_type(1) == cmd_complex) { + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } + // multiplying number*complex + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_number) { + rpn_swap(); + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } else + ERR_CONTEXT(ret_bad_operand_type); } -void do_divide_complexes() -{ - //(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2) - complex* right = (complex*)_stack->get_obj(0);//x+iy - complex* left = (complex*)_stack->get_obj(1);//a+ib - - //1. calc (x^2-y^2) in _calc_stack - number* ex = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_mul(ex->_value.mpfr, right->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd));//x2 - number* wy = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_mul(wy->_value.mpfr, right->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd));//y2 - CHECK_MPFR(mpfr_add(ex->_value.mpfr, ex->_value.mpfr, wy->_value.mpfr, floating_t::s_mpfr_rnd));//ex=x2+y2 +void do_divide_complexes() { + //(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2) + complex* right = (complex*)_stack->get_obj(0); // x+iy + complex* left = (complex*)_stack->get_obj(1); // a+ib - stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);//x+iy - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); - complex* left_sav = (complex*)_calc_stack.get_obj(1);//a+ib - complex* right_sav = (complex*)_calc_stack.get_obj(0);//x+iy + // 1. calc (x^2-y^2) in _calc_stack + number* ex = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_mul(ex->_value.mpfr, right->re()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); // x2 + number* wy = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_mul(wy->_value.mpfr, right->im()->mpfr, right->im()->mpfr, + floating_t::s_mpfr_rnd)); // y2 + CHECK_MPFR(mpfr_add(ex->_value.mpfr, ex->_value.mpfr, wy->_value.mpfr, + floating_t::s_mpfr_rnd)); // ex=x2+y2 - //2. left.re=ax+by - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left_sav->re()->mpfr, right_sav->re()->mpfr, floating_t::s_mpfr_rnd));//left.re=ax - CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, right_sav->im()->mpfr, floating_t::s_mpfr_rnd));//right.re=by - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd));//left.re=ax+by + stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); // x+iy + stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + complex* left_sav = (complex*)_calc_stack.get_obj(1); // a+ib + complex* right_sav = (complex*)_calc_stack.get_obj(0); // x+iy - //3. left.im=bx-ay - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->im()->mpfr, right_sav->re()->mpfr, floating_t::s_mpfr_rnd));//left.im=bx - CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->re()->mpfr, right_sav->im()->mpfr, floating_t::s_mpfr_rnd));//right.im=ay - CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd));//left.im=bx-ay + // 2. left.re=ax+by + CHECK_MPFR(mpfr_mul(left->re()->mpfr, left_sav->re()->mpfr, + right_sav->re()->mpfr, + floating_t::s_mpfr_rnd)); // left.re=ax + CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, + right_sav->im()->mpfr, + floating_t::s_mpfr_rnd)); // right.re=by + CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, + floating_t::s_mpfr_rnd)); // left.re=ax+by - //4. left.re/=(x^2-y^2), left.im/=(x^2+y^2) - CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, ex->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, ex->_value.mpfr, floating_t::s_mpfr_rnd)); + // 3. left.im=bx-ay + CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->im()->mpfr, + right_sav->re()->mpfr, + floating_t::s_mpfr_rnd)); // left.im=bx + CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->re()->mpfr, + right_sav->im()->mpfr, + floating_t::s_mpfr_rnd)); // right.im=ay + CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, + floating_t::s_mpfr_rnd)); // left.im=bx-ay + // 4. left.re/=(x^2-y^2), left.im/=(x^2+y^2) + CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, ex->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, ex->_value.mpfr, + floating_t::s_mpfr_rnd)); + + _stack->pop_back(); + _calc_stack.pop_back(4); +} + +void rpn_div() { + MIN_ARGUMENTS(2); + + // dividing 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(); + CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, + right->_value.mpfr, floating_t::s_mpfr_rnd)); + } + // dividing complexes + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_complex) + do_divide_complexes(); + // dividing complex/number + else if (_stack->get_type(0) == cmd_number && + _stack->get_type(1) == cmd_complex) { + number* right = (number*)_stack->pop_back(); + complex* left = (complex*)_stack->back(); + CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + } + // dividing number/complex + else if (_stack->get_type(0) == cmd_complex && + _stack->get_type(1) == cmd_number) { + // 1. copy out + stack::copy_and_push_back(*_stack, _stack->size() - 1, + _calc_stack); // complex + stack::copy_and_push_back(*_stack, _stack->size() - 2, + _calc_stack); // number + _stack->pop_back(2); + + // 2. copy back (2 complexes on stack) + stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, + *_stack); // complex back to stack + stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, + *_stack); // complex back to stack + + // 3. set complex level 2 to (number,0) + complex* new_cplx = (complex*)_stack->get_obj(1); + CHECK_MPFR(mpfr_set(new_cplx->re()->mpfr, + ((number*)_calc_stack.get_obj(0))->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set_ui(new_cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); + _calc_stack.pop_back(2); + + // 4. divide + do_divide_complexes(); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +void rpn_neg() { + MIN_ARGUMENTS(1); + + if (_stack->get_type(0) == cmd_number) { + number* left = (number*)_stack->back(); + CHECK_MPFR( + mpfr_neg(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + } else if (_stack->get_type(0) == cmd_complex) { + complex* left = (complex*)_stack->back(); + CHECK_MPFR( + mpfr_neg(left->re()->mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR( + mpfr_neg(left->im()->mpfr, left->im()->mpfr, floating_t::s_mpfr_rnd)); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +void rpn_inv() { + MIN_ARGUMENTS(1); + + if (_stack->get_type(0) == cmd_number) { + number* left = (number*)_stack->back(); + CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, + floating_t::s_mpfr_rnd)); + } else if (_stack->get_type(0) == cmd_complex) { + // 1. duplicate + rpn_dup(); + // 2. set complex level 2 to (1,0) + complex* cplx = (complex*)_stack->get_obj(1); + CHECK_MPFR(mpfr_set_ui(cplx->re()->mpfr, 1UL, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set_ui(cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); + // 3. divide + do_divide_complexes(); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +void rpn_purcent() { + 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(); + + CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, + floating_t::s_mpfr_rnd)); +} + +void rpn_purcentCH() { + 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(); + + CHECK_MPFR(mpfr_mul_si(right->_value.mpfr, right->_value.mpfr, 100L, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, + floating_t::s_mpfr_rnd)); +} + +void rpn_power() { + MIN_ARGUMENTS(2); + bool done_on_real = false; + + if (_stack->get_type(1) == cmd_number) { + ARG_MUST_BE_OF_TYPE(0, cmd_number); + number* right = (number*)_stack->get_obj(0); + number* left = (number*)_stack->get_obj(1); + + if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) { + CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, + right->_value.mpfr, floating_t::s_mpfr_rnd)); + _stack->pop_back(); + done_on_real = true; + } else { + // copy power out + stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_back(); + + // negative number -> complex number + _stack->allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, + floating_t::s_mpfr_rnd)); + rpn_r2c(); + + // copy power back + stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + _calc_stack.pop_back(); + } + } + + // carrefull, no 'else' here + if (!done_on_real) { + if (_stack->get_type(1) == cmd_complex) { + ARG_MUST_BE_OF_TYPE(0, cmd_number); + + // power on tmp stack + stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_back(); + + // switch complex to polar + complex* cplx = (complex*)_stack->back(); + rpn_r2p(); + + // new abs=abs^exponent + number* exponent = (number*)_calc_stack.back(); + CHECK_MPFR(mpfr_pow(cplx->re()->mpfr, cplx->re()->mpfr, + exponent->_value.mpfr, floating_t::s_mpfr_rnd)); + + // new arg=arg*exponent + CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, + exponent->_value.mpfr, floating_t::s_mpfr_rnd)); + + // back to cartesian + rpn_p2r(); + _calc_stack.pop_back(); + } else + ERR_CONTEXT(ret_bad_operand_type); + } +} + +void rpn_squareroot() { + if (_stack->get_type(0) == cmd_number) { + number* left = (number*)_stack->back(); + + if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) + CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, + floating_t::s_mpfr_rnd)); + else { + // negative number -> complex square root + _stack->allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, + floating_t::s_mpfr_rnd)); + rpn_r2c(); + _stack->allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, + floating_t::s_mpfr_rnd)); + rpn_power(); + } + } else if (_stack->get_type(0) == cmd_complex) { + // calc cplx^0.5 + _stack->allocate_back(number::calc_size(), cmd_number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, + floating_t::s_mpfr_rnd)); + rpn_power(); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +void rpn_square() { + MIN_ARGUMENTS(1); + + if (_stack->get_type(0) == cmd_number) { + number* left = (number*)_stack->back(); + CHECK_MPFR( + mpfr_sqr(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + } else if (_stack->get_type(0) == cmd_complex) { + rpn_dup(); + rpn_mul(); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +void rpn_modulo() { + 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(); + + CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); +} + +void rpn_abs() { + MIN_ARGUMENTS(1); + + if (_stack->get_type(0) == cmd_number) { + number* left = (number*)_stack->back(); + CHECK_MPFR( + mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + } else if (_stack->get_type(0) == cmd_complex) { + // 1. copy out -> calc x2+iy2 + stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); - _calc_stack.pop_back(4); + + // 2. calc x2+iy2 + complex* cplx = (complex*)_calc_stack.back(); + CHECK_MPFR(mpfr_mul(cplx->re()->mpfr, cplx->re()->mpfr, cplx->re()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, cplx->im()->mpfr, + floating_t::s_mpfr_rnd)); + + // 3. new real on stack + _stack->allocate_back(number::calc_size(), cmd_number); + number* module = (number*)_stack->back(); + + // 4. set it to |x2+y2| then take sqrt + CHECK_MPFR(mpfr_set(module->_value.mpfr, cplx->re()->mpfr, + floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_add(module->_value.mpfr, module->_value.mpfr, + cplx->im()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sqrt(module->_value.mpfr, module->_value.mpfr, + floating_t::s_mpfr_rnd)); + + _calc_stack.pop_back(); + } else + ERR_CONTEXT(ret_bad_operand_type); } -void rpn_div() -{ - MIN_ARGUMENTS(2); - - // dividing 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(); - CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // dividing complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) - do_divide_complexes(); - // dividing complex/number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) - { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - } - // dividing number/complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) - { - //1. copy out - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);//complex - stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);//number - _stack->pop_back(2); - - //2. copy back (2 complexes on stack) - stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);//complex back to stack - stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);//complex back to stack - - //3. set complex level 2 to (number,0) - complex* new_cplx = (complex*)_stack->get_obj(1); - CHECK_MPFR(mpfr_set(new_cplx->re()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_ui(new_cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(2); - - //4. divide - do_divide_complexes(); - } - else - ERR_CONTEXT(ret_bad_operand_type); +void rpn_hex() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ((number*)_stack->back())->_representation = number::hex; + number::s_decimal_digits = 0; } -void rpn_neg() -{ - MIN_ARGUMENTS(1); - - if (_stack->get_type(0) == cmd_number) - { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_neg(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else if (_stack->get_type(0) == cmd_complex) - { - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_neg(left->re()->mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_neg(left->im()->mpfr, left->im()->mpfr, floating_t::s_mpfr_rnd)); - } - else - ERR_CONTEXT(ret_bad_operand_type); +void rpn_bin() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ((number*)_stack->back())->_representation = number::bin; } -void rpn_inv() -{ - MIN_ARGUMENTS(1); - - if (_stack->get_type(0) == cmd_number) - { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else if (_stack->get_type(0) == cmd_complex) - { - //1. duplicate - rpn_dup(); - //2. set complex level 2 to (1,0) - complex* cplx = (complex*)_stack->get_obj(1); - CHECK_MPFR(mpfr_set_ui(cplx->re()->mpfr, 1UL, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_ui(cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); - //3. divide - do_divide_complexes(); - } - else - ERR_CONTEXT(ret_bad_operand_type); +void rpn_dec() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ((number*)_stack->back())->_representation = number::dec; } -void rpn_purcent() -{ - 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(); - - CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, floating_t::s_mpfr_rnd)); +void rpn_base() { + MIN_ARGUMENTS(2); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(1, cmd_number); + if (mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MIN) >= + 0 && + mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MAX) <= + 0) { + int base = (int)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, + floating_t::s_mpfr_rnd); + ((number*)_stack->get_obj(0))->_base = base; + ((number*)_stack->get_obj(0))->_representation = number::base; + } else + ERR_CONTEXT(ret_out_of_range); } -void rpn_purcentCH() -{ - MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); +void rpn_fact() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* right = (number*)_stack->pop_back(); - number* left = (number*)_stack->back(); + // fact(n) = gamma(n+1) + number* left = (number*)_stack->back(); + number* right = + (number*)_stack->allocate_back(number::calc_size(), cmd_number); + right->_value = 1L; + rpn_plus(); - CHECK_MPFR(mpfr_mul_si(right->_value.mpfr, right->_value.mpfr, 100L, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR( + mpfr_gamma(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); } -void rpn_power() -{ - MIN_ARGUMENTS(2); - bool done_on_real = false; - - if (_stack->get_type(1) == cmd_number) - { - ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* right = (number*)_stack->get_obj(0); - number* left = (number*)_stack->get_obj(1); - - if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) - { - CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - _stack->pop_back(); - done_on_real = true; - } - else - { - // copy power out - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); - _stack->pop_back(); - - // negative number -> complex number - _stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); - rpn_r2c(); - - // copy power back - stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack); - _calc_stack.pop_back(); - } - } - - // carrefull, no 'else' here - if (!done_on_real) - { - if (_stack->get_type(1) == cmd_complex) - { - ARG_MUST_BE_OF_TYPE(0, cmd_number); - - //power on tmp stack - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); - _stack->pop_back(); - - //switch complex to polar - complex* cplx = (complex*)_stack->back(); - rpn_r2p(); - - //new abs=abs^exponent - number* exponent = (number*)_calc_stack.back(); - CHECK_MPFR(mpfr_pow(cplx->re()->mpfr, cplx->re()->mpfr, exponent->_value.mpfr, floating_t::s_mpfr_rnd)); - - //new arg=arg*exponent - CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, exponent->_value.mpfr, floating_t::s_mpfr_rnd)); - - //back to cartesian - rpn_p2r(); - _calc_stack.pop_back(); - } - else - ERR_CONTEXT(ret_bad_operand_type); - } -} - -void rpn_squareroot() -{ - if (_stack->get_type(0) == cmd_number) - { - number* left = (number*)_stack->back(); - - if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) - CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - else - { - // negative number -> complex square root - _stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); - rpn_r2c(); - _stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); - rpn_power(); - } - } - else if (_stack->get_type(0) == cmd_complex) - { - // calc cplx^0.5 - _stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); - rpn_power(); - } - else - ERR_CONTEXT(ret_bad_operand_type); -} - -void rpn_square() -{ - MIN_ARGUMENTS(1); - - if (_stack->get_type(0) == cmd_number) - { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_sqr(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else if (_stack->get_type(0) == cmd_complex) - { - rpn_dup(); - rpn_mul(); - } - else - ERR_CONTEXT(ret_bad_operand_type); -} - -void rpn_modulo() -{ - 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(); - - CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); -} - -void rpn_abs() -{ - MIN_ARGUMENTS(1); - - if (_stack->get_type(0) == cmd_number) - { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } - else if (_stack->get_type(0) == cmd_complex) - { - //1. copy out -> calc x2+iy2 - stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack); - _stack->pop_back(); - - //2. calc x2+iy2 - complex* cplx = (complex*)_calc_stack.back(); - CHECK_MPFR(mpfr_mul(cplx->re()->mpfr, cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); - - //3. new real on stack - _stack->allocate_back(number::calc_size(), cmd_number); - number* module = (number*)_stack->back(); - - //4. set it to |x2+y2| then take sqrt - CHECK_MPFR(mpfr_set(module->_value.mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(module->_value.mpfr, module->_value.mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sqrt(module->_value.mpfr, module->_value.mpfr, floating_t::s_mpfr_rnd)); - - _calc_stack.pop_back(); - } - else - ERR_CONTEXT(ret_bad_operand_type); -} - -void rpn_hex() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::hex; - number::s_decimal_digits = 0; -} - -void rpn_bin() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::bin; -} - -void rpn_dec() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::dec; -} - -void rpn_base() -{ - MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MIN) >= 0 && mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MAX) <= 0) - { - int base = (int)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); - ((number*)_stack->get_obj(0))->_base = base; - ((number*)_stack->get_obj(0))->_representation = number::base; - } - else - ERR_CONTEXT(ret_out_of_range); -} - -void rpn_fact() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_sign() { + MIN_ARGUMENTS(1); + if (_stack->get_type(0) == cmd_number) { // fact(n) = gamma(n+1) number* left = (number*)_stack->back(); - number* right = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - right->_value = 1L; - rpn_plus(); - - CHECK_MPFR(mpfr_gamma(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + int result = mpfr_sgn(left->_value.mpfr); + left->_value = (long)result; + } else if (_stack->get_type(0) == cmd_complex) { + // calc x/sqrt(x*x+y*y) +iy/sqrt(x*x+y*y) + rpn_dup(); + rpn_abs(); + rpn_div(); + } else + ERR_CONTEXT(ret_bad_operand_type); } -void rpn_sign() -{ - MIN_ARGUMENTS(1); +void rpn_mant() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - if (_stack->get_type(0) == cmd_number) - { - // fact(n) = gamma(n+1) - number* left = (number*)_stack->back(); - int result = mpfr_sgn(left->_value.mpfr); - left->_value = (long)result; + number* left = (number*)_stack->back(); + + if (mpfr_number_p(left->_value.mpfr)) { + if (mpfr_zero_p(left->_value.mpfr)) + left->_value = 0.0; + else { + mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); + + number* one = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* ten = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + ten->_value = 10L; + + one->_value = 1L; + while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) + mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, + floating_t::s_mpfr_rnd); + + one->_value = 0.1; + while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) + mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, + floating_t::s_mpfr_rnd); + + _calc_stack.pop_back(2); } - else if (_stack->get_type(0) == cmd_complex) - { - // calc x/sqrt(x*x+y*y) +iy/sqrt(x*x+y*y) - rpn_dup(); - rpn_abs(); - rpn_div(); + } else + ERR_CONTEXT(ret_out_of_range); +} + +void rpn_xpon() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + + number* left = (number*)_stack->back(); + + if (mpfr_number_p(left->_value.mpfr)) { + if (mpfr_zero_p(left->_value.mpfr)) + left->_value = 0.0; + else { + double exponant = 0.0; + mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); + + number* one = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* ten = + (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + ten->_value = 10L; + + one->_value = 1L; + while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) { + mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, + floating_t::s_mpfr_rnd); + exponant += 1.0; + } + + one->_value = 0.1; + while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) { + mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, + floating_t::s_mpfr_rnd); + exponant -= 1.0; + } + + left->_value = exponant; + + _calc_stack.pop_back(); + _calc_stack.pop_back(); } - else - ERR_CONTEXT(ret_bad_operand_type); + } else + ERR_CONTEXT(ret_out_of_range); } -void rpn_mant() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_floor() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* left = (number*)_stack->back(); + number* left = (number*)_stack->back(); - if (mpfr_number_p(left->_value.mpfr)) - { - if (mpfr_zero_p(left->_value.mpfr)) - left->_value = 0.0; - else - { - mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); - - number* one = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - number* ten = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - ten->_value = 10L; - - one->_value = 1L; - while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) - mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); - - one->_value = 0.1; - while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) - mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); - - _calc_stack.pop_back(2); - } - } - else - ERR_CONTEXT(ret_out_of_range); + CHECK_MPFR(mpfr_floor(left->_value.mpfr, left->_value.mpfr)); } -void rpn_xpon() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_ceil() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* left = (number*)_stack->back(); + number* left = (number*)_stack->back(); - if (mpfr_number_p(left->_value.mpfr)) - { - if (mpfr_zero_p(left->_value.mpfr)) - left->_value = 0.0; - else - { - double exponant = 0.0; - mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); - - number* one = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - number* ten = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - ten->_value = 10L; - - one->_value = 1L; - while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) - { - mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); - exponant+=1.0; - } - - one->_value = 0.1; - while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) - { - mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); - exponant-=1.0; - } - - left->_value = exponant; - - _calc_stack.pop_back(); - _calc_stack.pop_back(); - } - } - else - ERR_CONTEXT(ret_out_of_range); + CHECK_MPFR(mpfr_ceil(left->_value.mpfr, left->_value.mpfr)); } -void rpn_floor() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_fp() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* left = (number*)_stack->back(); + number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_floor(left->_value.mpfr, left->_value.mpfr)); + CHECK_MPFR( + mpfr_frac(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); } -void rpn_ceil() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_ip() { + MIN_ARGUMENTS(1); + ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* left = (number*)_stack->back(); + number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_ceil(left->_value.mpfr, left->_value.mpfr)); + CHECK_MPFR(mpfr_trunc(left->_value.mpfr, left->_value.mpfr)); } -void rpn_fp() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_min() { + MIN_ARGUMENTS(2); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* left = (number*)_stack->back(); + number* right = (number*)_stack->pop_back(); + number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_frac(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_min(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); } -void rpn_ip() -{ - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); +void rpn_max() { + MIN_ARGUMENTS(2); + ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* left = (number*)_stack->back(); + number* right = (number*)_stack->pop_back(); + number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_trunc(left->_value.mpfr, left->_value.mpfr)); -} - -void rpn_min() -{ - 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(); - - CHECK_MPFR(mpfr_min(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); -} - -void rpn_max() -{ - 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(); - - CHECK_MPFR(mpfr_max(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_max(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, + floating_t::s_mpfr_rnd)); } diff --git a/src/rpn-stack.hpp b/src/rpn-stack.hpp index 58c5d7e..6f72ca5 100644 --- a/src/rpn-stack.hpp +++ b/src/rpn-stack.hpp @@ -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;isize()-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;isize()-1, _calc_stack); - (void)_stack->pop_back(); - } - - for(int i=1;iback())->_value.mpfr, floating_t::s_mpfr_rnd); - MIN_ARGUMENTS(args+1); - _stack->pop_back(); - - for(int i=0;isize()-1, _calc_stack); - (void)_stack->pop_back(); - } - - stack::copy_and_push_back(_calc_stack, _calc_stack.size()-args, *_stack); - - for(int i=1;isize()-2, *_stack); + stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); } diff --git a/src/rpn-store.hpp b/src/rpn-store.hpp index 01876ca..6dbda70 100644 --- a/src/rpn-store.hpp +++ b/src/rpn-store.hpp @@ -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(); } diff --git a/src/rpn-string.hpp b/src/rpn-string.hpp index c2946e2..195a784 100644 --- a/src/rpn-string.hpp +++ b/src/rpn-string.hpp @@ -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; + } } diff --git a/src/rpn-test-core.hpp b/src/rpn-test-core.hpp index 46b23b6..955ea40 100644 --- a/src/rpn-test-core.hpp +++ b/src/rpn-test-core.hpp @@ -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()); } diff --git a/src/rpn-test.hpp b/src/rpn-test.hpp index 831fde5..cb14afb 100644 --- a/src/rpn-test.hpp +++ b/src/rpn-test.hpp @@ -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(); } diff --git a/src/rpn-trig.hpp b/src/rpn-trig.hpp index 02c734d..c05ac92 100644 --- a/src/rpn-trig.hpp +++ b/src/rpn-trig.hpp @@ -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); } diff --git a/src/stack.hpp b/src/stack.hpp index 7e1c01b..7d00584 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -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::iterator i = _map.find(name); - object* local = NULL; + object* add(const string name, object* obj, unsigned int size) { + map::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::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::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::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::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::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::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::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::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 _map; + private: + map _map; }; -#endif // __stack_h__ +#endif // __stack_h__ diff --git a/src/version.h b/src/version.h index 41ce72c..0709c80 100644 --- a/src/version.h +++ b/src/version.h @@ -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";