mirror of
https://github.com/louisrubet/rpn
synced 2024-12-27 09:58:56 +01:00
#210: google-styled code
This commit is contained in:
parent
51c49c1aed
commit
abe2bd12e8
23 changed files with 4729 additions and 5184 deletions
1
src/.clang-format
Normal file
1
src/.clang-format
Normal file
|
@ -0,0 +1 @@
|
||||||
|
BasedOnStyle: Google
|
|
@ -22,7 +22,8 @@
|
||||||
// 128 bits significand precision
|
// 128 bits significand precision
|
||||||
#define MPFR_DEFAULT_PREC_BITS 128
|
#define MPFR_DEFAULT_PREC_BITS 128
|
||||||
|
|
||||||
// 128 bits significand storing length in bytes, result of mpfr_custom_get_size(128)
|
// 128 bits significand storing length in bytes, result of
|
||||||
|
// mpfr_custom_get_size(128)
|
||||||
#define MPFR_DEFAULT_STORING_LENGTH_BYTES 16
|
#define MPFR_DEFAULT_STORING_LENGTH_BYTES 16
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
|
@ -42,37 +43,46 @@
|
||||||
#define MPFR_FORMAT_SCI "Re"
|
#define MPFR_FORMAT_SCI "Re"
|
||||||
#define MPFR_FORMAT_HEX "%Ra"
|
#define MPFR_FORMAT_HEX "%Ra"
|
||||||
|
|
||||||
#define MPFR_RND_STRINGS { "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
|
#define MPFR_RND_STRINGS \
|
||||||
|
{ "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
|
||||||
|
|
||||||
// return values, used by all classes
|
// return values, used by all classes
|
||||||
//
|
//
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ret_ok,
|
ret_ok,
|
||||||
ret_unknown_err,
|
ret_unknown_err,
|
||||||
ret_missing_operand,
|
ret_missing_operand,
|
||||||
ret_bad_operand_type,
|
ret_bad_operand_type,
|
||||||
ret_out_of_range,
|
ret_out_of_range,
|
||||||
ret_unknown_variable,
|
ret_unknown_variable,
|
||||||
ret_internal,
|
ret_internal,
|
||||||
ret_deadly,
|
ret_deadly,
|
||||||
ret_good_bye,
|
ret_good_bye,
|
||||||
ret_not_impl,
|
ret_not_impl,
|
||||||
ret_nop,
|
ret_nop,
|
||||||
ret_syntax,
|
ret_syntax,
|
||||||
ret_div_by_zero,
|
ret_div_by_zero,
|
||||||
ret_runtime_error,
|
ret_runtime_error,
|
||||||
ret_abort_current_entry,
|
ret_abort_current_entry,
|
||||||
ret_max
|
ret_max
|
||||||
} ret_value;
|
} ret_value;
|
||||||
|
|
||||||
#define RET_VALUE_STRINGS { \
|
#define RET_VALUE_STRINGS \
|
||||||
"ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", \
|
{ \
|
||||||
"deadly", "goodbye", "not implemented", "no operation", "syntax error", "division by zero", "runtime error", "aborted current entry" \
|
"ok", "unknown command", "missing operand", "bad operand type", \
|
||||||
}
|
"out of range", "unknown variable", "internal error, aborting", \
|
||||||
|
"deadly", "goodbye", "not implemented", "no operation", \
|
||||||
|
"syntax error", "division by zero", "runtime error", \
|
||||||
|
"aborted current entry" \
|
||||||
|
}
|
||||||
|
|
||||||
// command types
|
// command types
|
||||||
//
|
//
|
||||||
#define CMD_TYPE_STRINGS { "undef", "number", "complex", "string", "symbol", "program", "keyword", "keyword" }
|
#define CMD_TYPE_STRINGS \
|
||||||
|
{ \
|
||||||
|
"undef", "number", "complex", "string", "symbol", "program", "keyword", \
|
||||||
|
"keyword" \
|
||||||
|
}
|
||||||
|
|
||||||
// history
|
// history
|
||||||
#define HISTORY_FILE ".rpn_history"
|
#define HISTORY_FILE ".rpn_history"
|
||||||
|
@ -99,14 +109,14 @@ typedef enum {
|
||||||
#error "Invalid MPFR Exp format"
|
#error "Invalid MPFR Exp format"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#define MAX(h,i) ((h) > (i) ? (h) : (i))
|
#define MAX(h, i) ((h) > (i) ? (h) : (i))
|
||||||
|
|
||||||
#define MPFR_EXP_INF (MPFR_EXP_MIN+3)
|
#define MPFR_EXP_INF (MPFR_EXP_MIN + 3)
|
||||||
#define MPFR_EXP_NAN (MPFR_EXP_MIN+2)
|
#define MPFR_EXP_NAN (MPFR_EXP_MIN + 2)
|
||||||
#define MPFR_EXP(x) ((x)->_mpfr_exp)
|
#define MPFR_EXP(x) ((x)->_mpfr_exp)
|
||||||
#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF)
|
#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF)
|
||||||
#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x),0))
|
#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
||||||
#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN)
|
#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN)
|
||||||
#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF)
|
#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF)
|
||||||
#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0)
|
#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0)
|
||||||
|
|
133
src/debug.h
133
src/debug.h
|
@ -2,97 +2,92 @@
|
||||||
#define DEBUG_H
|
#define DEBUG_H
|
||||||
|
|
||||||
static void dump8(unsigned char* to_dump, unsigned long offset,
|
static void dump8(unsigned char* to_dump, unsigned long offset,
|
||||||
unsigned long size)
|
unsigned long size) {
|
||||||
{
|
const int block_size = 1;
|
||||||
const int block_size = 1;
|
const int block_per_line = 16;
|
||||||
const int block_per_line = 16;
|
int max_line = size / block_size;
|
||||||
int max_line = size / block_size;
|
unsigned char mychar;
|
||||||
unsigned char mychar;
|
int i;
|
||||||
int i;
|
int j;
|
||||||
int j;
|
for (i = 0; i < max_line; i++) {
|
||||||
for (i = 0; i < max_line; i++)
|
if ((i % block_per_line) == 0) {
|
||||||
{
|
if (i > 0) {
|
||||||
if ((i % block_per_line) == 0)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
printf(" ");
|
|
||||||
for (j = i - block_per_line; j < i; j++)
|
|
||||||
{
|
|
||||||
mychar = *(to_dump + j);
|
|
||||||
if ((mychar < 32) || (mychar >= 127))
|
|
||||||
mychar = '.';
|
|
||||||
printf("%c", mychar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n%08lX:", offset + i * block_size);
|
|
||||||
}
|
|
||||||
printf(" %02hhX", *(to_dump + i));
|
|
||||||
}
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
printf(" ");
|
printf(" ");
|
||||||
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++)
|
for (j = i - block_per_line; j < i; j++) {
|
||||||
{
|
mychar = *(to_dump + j);
|
||||||
mychar = *(to_dump + j);
|
if ((mychar < 32) || (mychar >= 127)) mychar = '.';
|
||||||
if ((mychar < 32) || (mychar >= 127))
|
printf("%c", mychar);
|
||||||
mychar = '.';
|
|
||||||
printf("%c", mychar);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
printf("\n%08lX:", offset + i * block_size);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf(" %02hhX", *(to_dump + i));
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
printf(" ");
|
||||||
|
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++) {
|
||||||
|
mychar = *(to_dump + j);
|
||||||
|
if ((mychar < 32) || (mychar >= 127)) mychar = '.';
|
||||||
|
printf("%c", mychar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
#define TRACE(...) do { printf(__VA_ARGS__); } while(0)
|
#define TRACE(...) \
|
||||||
|
do { \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
// chrono
|
// chrono
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static int chrono_next = 0;
|
static int chrono_next = 0;
|
||||||
static struct
|
static struct {
|
||||||
{
|
struct timespec ts_point;
|
||||||
struct timespec ts_point;
|
char comment[256];
|
||||||
char comment[256];
|
|
||||||
} chrono_point[24];
|
} chrono_point[24];
|
||||||
|
|
||||||
static void chrono_start()
|
static void chrono_start() {
|
||||||
{
|
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
|
||||||
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
|
strcpy(chrono_point[0].comment, "START");
|
||||||
strcpy(chrono_point[0].comment, "START");
|
chrono_next = 1;
|
||||||
chrono_next = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chrono_add(const char* comment)
|
static void chrono_add(const char* comment) {
|
||||||
{
|
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
|
||||||
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
|
strcpy(chrono_point[chrono_next].comment, comment);
|
||||||
strcpy(chrono_point[chrono_next].comment, comment);
|
chrono_next++;
|
||||||
chrono_next++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t chrono_diff_us(struct timespec* ts_from, struct timespec* ts_to)
|
static uint64_t chrono_diff_us(struct timespec* ts_from,
|
||||||
{
|
struct timespec* ts_to) {
|
||||||
uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL + ((uint64_t)ts_from->tv_nsec) / 1000UL;
|
uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL +
|
||||||
uint64_t to = (uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
|
((uint64_t)ts_from->tv_nsec) / 1000UL;
|
||||||
return to - from;
|
uint64_t to =
|
||||||
|
(uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
|
||||||
|
return to - from;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chrono_all_print(void)
|
static void chrono_all_print(void) {
|
||||||
{
|
for (int i = 1; i < chrono_next; i++) {
|
||||||
for(int i = 1; i < chrono_next; i++)
|
printf("CHRONO [%lu us] %s\n",
|
||||||
{
|
chrono_diff_us(&chrono_point[i - 1].ts_point,
|
||||||
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[i-1].ts_point, &chrono_point[i].ts_point), chrono_point[i].comment);
|
&chrono_point[i].ts_point),
|
||||||
}
|
chrono_point[i].comment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chrono_print(int chrono)
|
static void chrono_print(int chrono) {
|
||||||
{
|
if (chrono >= 1) {
|
||||||
if (chrono >= 1)
|
printf("CHRONO [%lu us] %s\n",
|
||||||
{
|
chrono_diff_us(&chrono_point[chrono - 1].ts_point,
|
||||||
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[chrono-1].ts_point, &chrono_point[chrono].ts_point), chrono_point[chrono].comment);
|
&chrono_point[chrono].ts_point),
|
||||||
}
|
chrono_point[chrono].comment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define max(a, b) (((a)>(b))?(a):(b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
234
src/main.cpp
234
src/main.cpp
|
@ -1,12 +1,12 @@
|
||||||
// std c
|
// std c
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
// internal includes
|
// internal includes
|
||||||
#include "program.hpp"
|
#include "program.hpp"
|
||||||
|
@ -16,149 +16,137 @@ static stack s_global_stack;
|
||||||
static program* s_prog_to_interrupt = NULL;
|
static program* s_prog_to_interrupt = NULL;
|
||||||
|
|
||||||
// actions to be done at rpn exit
|
// actions to be done at rpn exit
|
||||||
void exit_interactive_rpn()
|
void exit_interactive_rpn() {
|
||||||
{
|
struct passwd* pw = getpwuid(getuid());
|
||||||
struct passwd* pw = getpwuid(getuid());
|
if (pw != NULL) {
|
||||||
if (pw != NULL)
|
char history_path[PATH_MAX];
|
||||||
{
|
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||||
char history_path[PATH_MAX];
|
|
||||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
|
||||||
|
|
||||||
// trunc current history
|
// trunc current history
|
||||||
ofstream history(history_path, ios_base::out|ios_base::trunc);
|
ofstream history(history_path, ios_base::out | ios_base::trunc);
|
||||||
history.close();
|
history.close();
|
||||||
|
|
||||||
// save it
|
// save it
|
||||||
if (linenoiseHistorySave(history_path) != 0)
|
if (linenoiseHistorySave(history_path) != 0)
|
||||||
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno));
|
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n",
|
||||||
}
|
history_path, errno, strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// actions to be done at rpn exit
|
// actions to be done at rpn exit
|
||||||
void init_interactive_rpn()
|
void init_interactive_rpn() {
|
||||||
{
|
struct passwd* pw = getpwuid(getuid());
|
||||||
struct passwd* pw = getpwuid(getuid());
|
if (pw != NULL) {
|
||||||
if (pw != NULL)
|
char history_path[PATH_MAX];
|
||||||
{
|
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||||
char history_path[PATH_MAX];
|
|
||||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
|
||||||
|
|
||||||
// don't care about errors
|
// don't care about errors
|
||||||
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
|
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
|
||||||
linenoiseHistoryLoad(history_path);
|
linenoiseHistoryLoad(history_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle CtrlC signal
|
// handle CtrlC signal
|
||||||
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context)
|
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
|
||||||
{
|
if (s_prog_to_interrupt != NULL) {
|
||||||
if (s_prog_to_interrupt != NULL)
|
s_prog_to_interrupt->stop();
|
||||||
{
|
s_prog_to_interrupt = NULL;
|
||||||
s_prog_to_interrupt->stop();
|
}
|
||||||
s_prog_to_interrupt = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_interactive_rpn();
|
exit_interactive_rpn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle SIGSEGV signal
|
// handle SIGSEGV signal
|
||||||
static void segv_handler(int sig, siginfo_t* siginfo, void* context)
|
static void segv_handler(int sig, siginfo_t* siginfo, void* context) {
|
||||||
{
|
fprintf(stderr, "Internal error\n");
|
||||||
fprintf(stderr, "Internal error\n");
|
s_prog_to_interrupt->stop();
|
||||||
s_prog_to_interrupt->stop();
|
s_prog_to_interrupt = NULL;
|
||||||
s_prog_to_interrupt = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void catch_signals(program* prog)
|
static void catch_signals(program* prog) {
|
||||||
{
|
struct sigaction act;
|
||||||
struct sigaction act;
|
|
||||||
|
|
||||||
s_prog_to_interrupt = prog;
|
s_prog_to_interrupt = prog;
|
||||||
|
|
||||||
act.sa_sigaction = &ctrlc_handler;
|
act.sa_sigaction = &ctrlc_handler;
|
||||||
act.sa_flags = SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
if (sigaction(SIGINT, &act, NULL) < 0)
|
if (sigaction(SIGINT, &act, NULL) < 0)
|
||||||
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']", errno, strerror(errno));
|
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']",
|
||||||
|
errno, strerror(errno));
|
||||||
|
|
||||||
act.sa_sigaction = &segv_handler;
|
act.sa_sigaction = &segv_handler;
|
||||||
act.sa_flags = SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
if (sigaction(SIGSEGV, &act, NULL) < 0)
|
if (sigaction(SIGSEGV, &act, NULL) < 0)
|
||||||
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno));
|
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']",
|
||||||
|
errno, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[]) {
|
||||||
{
|
int ret = 0;
|
||||||
int ret = 0;
|
bool go_on = true;
|
||||||
bool go_on = true;
|
|
||||||
|
|
||||||
// apply default configuration
|
// apply default configuration
|
||||||
program::apply_default();
|
program::apply_default();
|
||||||
|
|
||||||
// run with interactive prompt
|
// run with interactive prompt
|
||||||
if (argc == 1)
|
if (argc == 1) {
|
||||||
{
|
// init history
|
||||||
// init history
|
init_interactive_rpn();
|
||||||
init_interactive_rpn();
|
|
||||||
|
|
||||||
// entry loop
|
// entry loop
|
||||||
while(go_on)
|
while (go_on) {
|
||||||
{
|
// make program from interactive entry
|
||||||
// make program from interactive entry
|
program prog;
|
||||||
program prog;
|
switch (program::entry(prog)) {
|
||||||
switch (program::entry(prog))
|
case ret_good_bye:
|
||||||
{
|
go_on = false;
|
||||||
case ret_good_bye:
|
break;
|
||||||
go_on = false;
|
case ret_abort_current_entry:
|
||||||
break;
|
break;
|
||||||
case ret_abort_current_entry:
|
default:
|
||||||
break;
|
// user could stop prog with CtrlC
|
||||||
default:
|
catch_signals(&prog);
|
||||||
// user could stop prog with CtrlC
|
|
||||||
catch_signals(&prog);
|
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
|
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
|
||||||
go_on = false;
|
go_on = false;
|
||||||
else
|
else
|
||||||
program::show_stack(s_global_stack);
|
program::show_stack(s_global_stack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// manage history and exit
|
|
||||||
exit_interactive_rpn();
|
|
||||||
}
|
|
||||||
// run with cmd line arguments
|
|
||||||
else
|
|
||||||
{
|
|
||||||
program prog;
|
|
||||||
string entry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// make one string from entry
|
|
||||||
for (i=1; i<argc; i++)
|
|
||||||
{
|
|
||||||
entry += argv[i];
|
|
||||||
entry += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// make program
|
|
||||||
ret = program::parse(entry.c_str(), prog);
|
|
||||||
if (ret == ret_ok)
|
|
||||||
{
|
|
||||||
string separator = "";
|
|
||||||
|
|
||||||
// user could stop prog with CtrlC
|
|
||||||
catch_signals(&prog);
|
|
||||||
|
|
||||||
// run it
|
|
||||||
ret = prog.run(s_global_stack, s_global_heap);
|
|
||||||
program::show_stack(s_global_stack, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mpfr_free_cache();
|
// manage history and exit
|
||||||
|
exit_interactive_rpn();
|
||||||
|
}
|
||||||
|
// run with cmd line arguments
|
||||||
|
else {
|
||||||
|
program prog;
|
||||||
|
string entry;
|
||||||
|
int i;
|
||||||
|
|
||||||
return ret;
|
// make one string from entry
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
entry += argv[i];
|
||||||
|
entry += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// make program
|
||||||
|
ret = program::parse(entry.c_str(), prog);
|
||||||
|
if (ret == ret_ok) {
|
||||||
|
string separator = "";
|
||||||
|
|
||||||
|
// user could stop prog with CtrlC
|
||||||
|
catch_signals(&prog);
|
||||||
|
|
||||||
|
// run it
|
||||||
|
ret = prog.run(s_global_stack, s_global_heap);
|
||||||
|
program::show_stack(s_global_stack, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpfr_free_cache();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
383
src/object.cpp
383
src/object.cpp
|
@ -1,9 +1,9 @@
|
||||||
#include <string>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <string>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include "mpfr.h"
|
|
||||||
#include "constant.h"
|
#include "constant.h"
|
||||||
|
#include "mpfr.h"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
// floating_t statics
|
// floating_t statics
|
||||||
|
@ -20,233 +20,198 @@ string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
|
||||||
//
|
//
|
||||||
const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
|
const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
|
||||||
|
|
||||||
static bool is_min(mpfr_t p, mpfr_prec_t prec)
|
static bool is_min(mpfr_t p, mpfr_prec_t prec) {
|
||||||
{
|
// see mpfr_vasprintf code
|
||||||
// see mpfr_vasprintf code
|
bool ret;
|
||||||
bool ret;
|
int round_away;
|
||||||
int round_away;
|
switch (floating_t::s_mpfr_rnd) {
|
||||||
switch (floating_t::s_mpfr_rnd)
|
case MPFR_RNDA:
|
||||||
{
|
round_away = 1;
|
||||||
case MPFR_RNDA:
|
break;
|
||||||
round_away = 1;
|
case MPFR_RNDD:
|
||||||
break;
|
round_away = MPFR_IS_NEG(p);
|
||||||
case MPFR_RNDD:
|
break;
|
||||||
round_away = MPFR_IS_NEG (p);
|
case MPFR_RNDU:
|
||||||
break;
|
round_away = MPFR_IS_POS(p);
|
||||||
case MPFR_RNDU:
|
break;
|
||||||
round_away = MPFR_IS_POS (p);
|
case MPFR_RNDN: {
|
||||||
break;
|
/* compare |p| to y = 0.5*10^(-prec) */
|
||||||
case MPFR_RNDN:
|
mpfr_t y;
|
||||||
{
|
mpfr_exp_t e = MAX(MPFR_PREC(p), 56);
|
||||||
/* compare |p| to y = 0.5*10^(-prec) */
|
mpfr_init2(y, e + 8);
|
||||||
mpfr_t y;
|
do {
|
||||||
mpfr_exp_t e = MAX (MPFR_PREC (p), 56);
|
/* find a lower approximation of
|
||||||
mpfr_init2 (y, e + 8);
|
0.5*10^(-prec) different from |p| */
|
||||||
do
|
e += 8;
|
||||||
{
|
mpfr_set_prec(y, e);
|
||||||
/* find a lower approximation of
|
mpfr_set_si(y, -prec, MPFR_RNDN);
|
||||||
0.5*10^(-prec) different from |p| */
|
mpfr_exp10(y, y, MPFR_RNDD);
|
||||||
e += 8;
|
mpfr_div_2ui(y, y, 1, MPFR_RNDN);
|
||||||
mpfr_set_prec (y, e);
|
} while (mpfr_cmpabs(y, p) == 0);
|
||||||
mpfr_set_si (y, -prec, MPFR_RNDN);
|
|
||||||
mpfr_exp10 (y, y, MPFR_RNDD);
|
|
||||||
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
|
|
||||||
} while (mpfr_cmpabs (y, p) == 0);
|
|
||||||
|
|
||||||
round_away = mpfr_cmpabs (y, p) < 0;
|
round_away = mpfr_cmpabs(y, p) < 0;
|
||||||
mpfr_clear (y);
|
mpfr_clear(y);
|
||||||
}
|
} break;
|
||||||
break;
|
default:
|
||||||
default:
|
round_away = 0;
|
||||||
round_away = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (round_away)
|
if (round_away) /* round away from zero: the last output digit is '1' */
|
||||||
/* round away from zero: the last output digit is '1' */
|
ret = true;
|
||||||
ret = true;
|
else
|
||||||
else
|
/* only zeros in fractional part */
|
||||||
/* only zeros in fractional part */
|
ret = false;
|
||||||
ret = false;
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL)
|
static void print_fix(FILE* stream, mpfr_t real, int base,
|
||||||
{
|
const char* write_after_sign = NULL) {
|
||||||
// see mpfr_vasprintf code
|
// see mpfr_vasprintf code
|
||||||
mpfr_exp_t exp = mpfr_get_exp(real);
|
mpfr_exp_t exp = mpfr_get_exp(real);
|
||||||
int digits = 0; //forced 0 digits after separator
|
int digits = 0; // forced 0 digits after separator
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real)))
|
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) {
|
||||||
{
|
if (MPFR_IS_NAN(real))
|
||||||
if (MPFR_IS_NAN(real))
|
fputs("nan", stream);
|
||||||
fputs("nan", stream);
|
else if (MPFR_IS_INF(real)) {
|
||||||
else if (MPFR_IS_INF(real))
|
if (MPFR_IS_NEG(real)) fputc('-', stream);
|
||||||
{
|
fputs("inf", stream);
|
||||||
if (MPFR_IS_NEG(real))
|
} else {
|
||||||
fputc('-', stream);
|
// zero
|
||||||
fputs("inf", stream);
|
if (MPFR_IS_NEG(real)) fputc('-', stream); // signed zero is allowed
|
||||||
}
|
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||||
else
|
fputc('0', stream);
|
||||||
{
|
if (digits > 0) {
|
||||||
// zero
|
fputc('.', stream);
|
||||||
if (MPFR_IS_NEG(real))
|
for (i = 0; i < digits; i++) fputc('0', stream);
|
||||||
fputc('-', stream);//signed zero is allowed
|
}
|
||||||
if (write_after_sign != NULL)
|
|
||||||
fputs(write_after_sign, stream);
|
|
||||||
fputc('0', stream);
|
|
||||||
if (digits > 0)
|
|
||||||
{
|
|
||||||
fputc('.', stream);
|
|
||||||
for(i = 0; i < digits; i++)
|
|
||||||
fputc('0', stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (exp < -digits)
|
} else if (exp < -digits) {
|
||||||
{
|
if (MPFR_IS_NEG(real)) fputc('-', stream);
|
||||||
if (MPFR_IS_NEG(real))
|
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||||
fputc('-', stream);
|
fputc('0', stream);
|
||||||
if (write_after_sign != NULL)
|
if (digits > 0) {
|
||||||
fputs(write_after_sign, stream);
|
fputc('.', stream);
|
||||||
|
for (i = 0; i < digits - 1; i++) fputc('0', stream);
|
||||||
|
|
||||||
|
if (is_min(real, digits))
|
||||||
|
fputc('1', stream);
|
||||||
|
else
|
||||||
fputc('0', stream);
|
fputc('0', stream);
|
||||||
if (digits > 0)
|
}
|
||||||
{
|
} else {
|
||||||
|
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
char* print_from;
|
||||||
|
if (str != NULL) {
|
||||||
|
int len = strlen(str);
|
||||||
|
print_from = str;
|
||||||
|
if (len > 0) {
|
||||||
|
if (print_from[0] == '-') {
|
||||||
|
fputc(print_from[0], stream);
|
||||||
|
len--;
|
||||||
|
print_from++;
|
||||||
|
} else if (print_from[0] == '+') {
|
||||||
|
len--;
|
||||||
|
print_from++;
|
||||||
|
}
|
||||||
|
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||||
|
if (exp < 0) {
|
||||||
|
fputc('0', stream);
|
||||||
|
if (digits > 0) {
|
||||||
|
fputc('.', stream);
|
||||||
|
for (i = 0; i < -(int)exp; i++) fputc('0', stream);
|
||||||
|
fputs(str, stream);
|
||||||
|
for (i = 0; i < (int)(digits - len + exp); i++) fputc('0', stream);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (exp == 0)
|
||||||
|
fputc('0', stream);
|
||||||
|
else
|
||||||
|
for (i = 0; i < (int)exp; i++) fputc(print_from[i], stream);
|
||||||
|
if (digits > 0) {
|
||||||
fputc('.', stream);
|
fputc('.', stream);
|
||||||
for (i = 0; i< digits - 1; i++)
|
|
||||||
fputc('0', stream);
|
|
||||||
|
|
||||||
if (is_min(real, digits))
|
int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
|
||||||
fputc('1', stream);
|
for (i = (int)exp; i < remaining + (int)exp; i++)
|
||||||
else
|
fputc(print_from[i], stream);
|
||||||
fputc('0', stream);
|
for (i = 0; i < (int)(exp + digits - len); i++) fputc('0', stream);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, floating_t::s_mpfr_rnd);
|
|
||||||
char* print_from;
|
|
||||||
if(str != NULL)
|
|
||||||
{
|
|
||||||
int len = strlen(str);
|
|
||||||
print_from = str;
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
if (print_from[0] == '-')
|
|
||||||
{
|
|
||||||
fputc(print_from[0], stream);
|
|
||||||
len--;
|
|
||||||
print_from++;
|
|
||||||
}
|
|
||||||
else if (print_from[0] == '+')
|
|
||||||
{
|
|
||||||
len--;
|
|
||||||
print_from++;
|
|
||||||
}
|
|
||||||
if (write_after_sign != NULL)
|
|
||||||
fputs(write_after_sign, stream);
|
|
||||||
if (exp < 0)
|
|
||||||
{
|
|
||||||
fputc('0', stream);
|
|
||||||
if (digits > 0)
|
|
||||||
{
|
|
||||||
fputc('.', stream);
|
|
||||||
for (i = 0; i < -(int)exp; i++)
|
|
||||||
fputc('0', stream);
|
|
||||||
fputs(str, stream);
|
|
||||||
for (i = 0; i < (int)(digits - len + exp); i++)
|
|
||||||
fputc('0', stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (exp == 0)
|
|
||||||
fputc('0', stream);
|
|
||||||
else
|
|
||||||
for (i = 0; i < (int)exp; i++)
|
|
||||||
fputc(print_from[i], stream);
|
|
||||||
if (digits > 0)
|
|
||||||
{
|
|
||||||
fputc('.', stream);
|
|
||||||
|
|
||||||
int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
|
|
||||||
for (i = (int)exp; i < remaining + (int)exp; i++)
|
|
||||||
fputc(print_from[i], stream);
|
|
||||||
for (i = 0; i < (int)(exp + digits - len); i++)
|
|
||||||
fputc('0', stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mpfr_free_str(str);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mpfr_free_str(str);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void object::show(FILE* stream)
|
void object::show(FILE* stream) {
|
||||||
{
|
int digits;
|
||||||
int digits;
|
char* str;
|
||||||
char* str;
|
char base[32];
|
||||||
char base[32];
|
|
||||||
|
|
||||||
switch(_type)
|
switch (_type) {
|
||||||
{
|
|
||||||
case cmd_number:
|
case cmd_number:
|
||||||
switch(((number*)this)->_representation)
|
switch (((number*)this)->_representation) {
|
||||||
{
|
case number::dec:
|
||||||
case number::dec:
|
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr);
|
((number*)this)->_value.mpfr);
|
||||||
break;
|
break;
|
||||||
case number::hex:
|
case number::hex:
|
||||||
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
|
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
|
||||||
break;
|
break;
|
||||||
case number::bin:
|
case number::bin:
|
||||||
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
|
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
|
||||||
break;
|
break;
|
||||||
case number::base:
|
case number::base:
|
||||||
sprintf(base, "%db", ((number*)this)->_base);
|
sprintf(base, "%db", ((number*)this)->_base);
|
||||||
print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base, base);
|
print_fix(stream, ((number*)this)->_value.mpfr,
|
||||||
break;
|
((number*)this)->_base, base);
|
||||||
default:
|
break;
|
||||||
fprintf(stream, "<unknown number representation>");
|
default:
|
||||||
break;
|
fprintf(stream, "<unknown number representation>");
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
case cmd_complex:
|
case cmd_complex:
|
||||||
switch(((complex*)this)->_representation)
|
switch (((complex*)this)->_representation) {
|
||||||
{
|
case number::dec:
|
||||||
case number::dec:
|
fprintf(stream, "(");
|
||||||
fprintf(stream, "(");
|
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr);
|
((complex*)this)->re()->mpfr);
|
||||||
fprintf(stream, ",");
|
fprintf(stream, ",");
|
||||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->im()->mpfr);
|
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||||
fprintf(stream, ")");
|
((complex*)this)->im()->mpfr);
|
||||||
break;
|
fprintf(stream, ")");
|
||||||
case number::hex:
|
break;
|
||||||
fprintf(stream, "(");
|
case number::hex:
|
||||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->re()->mpfr);
|
fprintf(stream, "(");
|
||||||
fprintf(stream, ",");
|
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
|
||||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->im()->mpfr);
|
((complex*)this)->re()->mpfr);
|
||||||
fprintf(stream, ")");
|
fprintf(stream, ",");
|
||||||
break;
|
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
|
||||||
default:
|
((complex*)this)->im()->mpfr);
|
||||||
fprintf(stream, "<unknown complex representation>");
|
fprintf(stream, ")");
|
||||||
}
|
break;
|
||||||
break;
|
default:
|
||||||
|
fprintf(stream, "<unknown complex representation>");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case cmd_string:
|
case cmd_string:
|
||||||
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
|
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
|
||||||
break;
|
break;
|
||||||
case cmd_program:
|
case cmd_program:
|
||||||
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
|
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
|
||||||
break;
|
break;
|
||||||
case cmd_symbol:
|
case cmd_symbol:
|
||||||
fprintf(stream, "'%s'", ((symbol*)this)->_value);
|
fprintf(stream, "'%s'", ((symbol*)this)->_value);
|
||||||
break;
|
break;
|
||||||
case cmd_keyword:
|
case cmd_keyword:
|
||||||
case cmd_branch:
|
case cmd_branch:
|
||||||
fprintf(stream, "%s", ((keyword*)this)->_value);
|
fprintf(stream, "%s", ((keyword*)this)->_value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stream, "< unknown object representation >");
|
fprintf(stream, "< unknown object representation >");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
482
src/object.hpp
482
src/object.hpp
|
@ -7,15 +7,15 @@
|
||||||
// definitions for objects
|
// definitions for objects
|
||||||
////
|
////
|
||||||
typedef enum {
|
typedef enum {
|
||||||
cmd_undef,
|
cmd_undef,
|
||||||
cmd_number,// floating point number
|
cmd_number, // floating point number
|
||||||
cmd_complex,// complex, couple of floating point numbers
|
cmd_complex, // complex, couple of floating point numbers
|
||||||
cmd_string,// string like "string"
|
cmd_string, // string like "string"
|
||||||
cmd_symbol,// symbol like 'symbol'
|
cmd_symbol, // symbol like 'symbol'
|
||||||
cmd_program,// program like << instructions >>
|
cmd_program, // program like << instructions >>
|
||||||
cmd_keyword,// langage keyword
|
cmd_keyword, // langage keyword
|
||||||
cmd_branch,// langage branch keyword
|
cmd_branch, // langage branch keyword
|
||||||
cmd_max
|
cmd_max
|
||||||
} cmd_type_t;
|
} cmd_type_t;
|
||||||
|
|
||||||
class program;
|
class program;
|
||||||
|
@ -26,330 +26,262 @@ typedef int (program::*branch_fn_t)(branch&);
|
||||||
|
|
||||||
// MPFR object
|
// MPFR object
|
||||||
////
|
////
|
||||||
struct floating_t
|
struct floating_t {
|
||||||
{
|
mpfr_prec_t mpfr_prec; // precision in bits
|
||||||
mpfr_prec_t mpfr_prec;// precision in bits
|
unsigned int mpfr_prec_bytes; // significand storing length in bytes
|
||||||
unsigned int mpfr_prec_bytes;// significand storing length in bytes
|
mpfr_t mpfr; // mpfr object
|
||||||
mpfr_t mpfr;//mpfr object
|
|
||||||
|
|
||||||
void init()
|
void init() {
|
||||||
{
|
void* significand = (void*)(this + 1);
|
||||||
void* significand = (void*)(this+1);
|
mpfr_prec = s_mpfr_prec;
|
||||||
mpfr_prec = s_mpfr_prec;
|
mpfr_prec_bytes = s_mpfr_prec_bytes;
|
||||||
mpfr_prec_bytes = s_mpfr_prec_bytes;
|
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
|
||||||
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
|
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
|
||||||
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void move()
|
void move() {
|
||||||
{
|
void* significand = (void*)(this + 1);
|
||||||
void* significand = (void*)(this+1);
|
mpfr_custom_move(mpfr, significand);
|
||||||
mpfr_custom_move(mpfr, significand);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
floating_t& operator=(const double val)
|
floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); }
|
||||||
{
|
|
||||||
mpfr_set_d(mpfr, val, s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
floating_t& operator=(const long int val)
|
floating_t& operator=(const long int val) {
|
||||||
{
|
mpfr_set_si(mpfr, val, s_mpfr_rnd);
|
||||||
mpfr_set_si(mpfr, val, s_mpfr_rnd);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
floating_t& operator=(const unsigned long val)
|
floating_t& operator=(const unsigned long val) {
|
||||||
{
|
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
|
||||||
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
operator double()
|
operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); }
|
||||||
{
|
|
||||||
return mpfr_get_d(mpfr, s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator int()
|
operator int() { return (int)mpfr_get_si(mpfr, s_mpfr_rnd); }
|
||||||
{
|
|
||||||
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator long()
|
|
||||||
{
|
|
||||||
return mpfr_get_si(mpfr, s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const floating_t right)
|
operator long() { return mpfr_get_si(mpfr, s_mpfr_rnd); }
|
||||||
{
|
|
||||||
return mpfr_cmp(mpfr, right.mpfr) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const floating_t right)
|
bool operator>(const floating_t right) {
|
||||||
{
|
return mpfr_cmp(mpfr, right.mpfr) > 0;
|
||||||
return mpfr_cmp(mpfr, right.mpfr) < 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// default precision in bits, precision length in bytes, rounding mode
|
bool operator<(const floating_t right) {
|
||||||
static mpfr_prec_t s_mpfr_prec;
|
return mpfr_cmp(mpfr, right.mpfr) < 0;
|
||||||
static unsigned int s_mpfr_prec_bytes;
|
}
|
||||||
static mpfr_rnd_t s_mpfr_rnd;
|
|
||||||
static const char* s_mpfr_rnd_str[5];
|
// default precision in bits, precision length in bytes, rounding mode
|
||||||
|
static mpfr_prec_t s_mpfr_prec;
|
||||||
|
static unsigned int s_mpfr_prec_bytes;
|
||||||
|
static mpfr_rnd_t s_mpfr_rnd;
|
||||||
|
static const char* s_mpfr_rnd_str[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
// object - a generic stack object
|
// object - a generic stack object
|
||||||
////
|
////
|
||||||
struct object
|
struct object {
|
||||||
{
|
// object type
|
||||||
// object type
|
cmd_type_t _type;
|
||||||
cmd_type_t _type;
|
unsigned int _size;
|
||||||
unsigned int _size;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
unsigned int size() { return _size; }
|
unsigned int size() { return _size; }
|
||||||
|
|
||||||
void show(FILE* stream = stdout);
|
void show(FILE* stream = stdout);
|
||||||
|
|
||||||
//
|
//
|
||||||
static const char* s_cmd_type_string[cmd_max];
|
static const char* s_cmd_type_string[cmd_max];
|
||||||
};
|
};
|
||||||
|
|
||||||
// stack objects derived from object
|
// stack objects derived from object
|
||||||
////
|
////
|
||||||
struct number : public object
|
struct number : public object {
|
||||||
{
|
// members
|
||||||
// members
|
enum { dec, hex, bin, base } _representation;
|
||||||
enum {
|
// base
|
||||||
dec,
|
// carefull: _base is used only if _representation = base
|
||||||
hex,
|
int _base;
|
||||||
bin,
|
// mind that float value is at the end of the object
|
||||||
base
|
// because its mantissa is just after the obj in memory
|
||||||
} _representation;
|
floating_t _value;
|
||||||
// base
|
|
||||||
// carefull: _base is used only if _representation = base
|
|
||||||
int _base;
|
|
||||||
// mind that float value is at the end of the object
|
|
||||||
// because its mantissa is just after the obj in memory
|
|
||||||
floating_t _value;
|
|
||||||
|
|
||||||
// publics
|
// publics
|
||||||
number() { _type = cmd_number; }
|
number() { _type = cmd_number; }
|
||||||
|
|
||||||
void init()
|
void init() {
|
||||||
{
|
_type = cmd_number;
|
||||||
_type = cmd_number;
|
_representation = dec;
|
||||||
_representation = dec;
|
_value.init();
|
||||||
_value.init();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void move()
|
void move() { _value.move(); }
|
||||||
{
|
|
||||||
_value.move();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(unsigned long value)
|
void set(unsigned long value) {
|
||||||
{
|
_type = cmd_number;
|
||||||
_type = cmd_number;
|
_value = value;
|
||||||
_value = value;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int calc_size()
|
static unsigned int calc_size() {
|
||||||
{
|
return (unsigned int)(sizeof(number) + floating_t::s_mpfr_prec_bytes);
|
||||||
return (unsigned int)(sizeof(number)+floating_t::s_mpfr_prec_bytes);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// representation mode
|
// representation mode
|
||||||
typedef enum {
|
typedef enum { std, fix, sci } mode_enum;
|
||||||
std,
|
static mode_enum s_mode;
|
||||||
fix,
|
|
||||||
sci
|
|
||||||
} mode_enum;
|
|
||||||
static mode_enum s_mode;
|
|
||||||
|
|
||||||
// precision
|
// precision
|
||||||
static int s_decimal_digits;
|
static int s_decimal_digits;
|
||||||
static string s_mpfr_printf_format;
|
static string s_mpfr_printf_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
// stack objects derived from object
|
// stack objects derived from object
|
||||||
////
|
////
|
||||||
struct complex : public object
|
struct complex : public object {
|
||||||
{
|
enum { dec, hex } _representation;
|
||||||
enum {
|
// mind that re float value is at the end of the object
|
||||||
dec,
|
// because its mantissa is just after the obj in memory
|
||||||
hex
|
floating_t _re;
|
||||||
} _representation;
|
|
||||||
// mind that re float value is at the end of the object
|
|
||||||
// because its mantissa is just after the obj in memory
|
|
||||||
floating_t _re;
|
|
||||||
|
|
||||||
complex() { _type = cmd_complex; }
|
complex() { _type = cmd_complex; }
|
||||||
|
|
||||||
// re and im float values are at the end of the object
|
// re and im float values are at the end of the object
|
||||||
floating_t* re() { return &_re; }
|
floating_t* re() { return &_re; }
|
||||||
floating_t* im() { return (floating_t*)((char*)&_re + sizeof(floating_t) + _re.mpfr_prec_bytes); }
|
floating_t* im() {
|
||||||
|
return (floating_t*)((char*)&_re + sizeof(floating_t) +
|
||||||
|
_re.mpfr_prec_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init() {
|
||||||
{
|
_type = cmd_complex;
|
||||||
_type = cmd_complex;
|
_representation = dec;
|
||||||
_representation = dec;
|
re()->init();
|
||||||
re()->init();
|
im()->init();
|
||||||
im()->init();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void move()
|
void move() {
|
||||||
{
|
re()->move();
|
||||||
re()->move();
|
im()->move();
|
||||||
im()->move();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int calc_size()
|
static unsigned int calc_size() {
|
||||||
{
|
return (
|
||||||
return (unsigned int)(sizeof(complex)+2*(sizeof(floating_t)+floating_t::s_mpfr_prec_bytes));
|
unsigned int)(sizeof(complex) +
|
||||||
}
|
2 * (sizeof(floating_t) + floating_t::s_mpfr_prec_bytes));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ostring : public object
|
struct ostring : public object {
|
||||||
{
|
// ostring may first have been allocated with len+1 bytes
|
||||||
// ostring may first have been allocated with len+1 bytes
|
void set(const char* value, unsigned int len) {
|
||||||
void set(const char* value, unsigned int len)
|
_type = cmd_string;
|
||||||
{
|
if (value != NULL) {
|
||||||
_type = cmd_string;
|
if (len > 0) (void)memcpy(_value, value, len);
|
||||||
if (value != NULL)
|
_value[len] = 0;
|
||||||
{
|
_len = len;
|
||||||
if (len>0)
|
} else {
|
||||||
(void)memcpy(_value, value, len);
|
_value[_len] = 0;
|
||||||
_value[len] = 0;
|
_len = 0;
|
||||||
_len = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_value[_len] = 0;
|
|
||||||
_len = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// length of _value, not including the terminal '\0'
|
// length of _value, not including the terminal '\0'
|
||||||
unsigned int _len;
|
unsigned int _len;
|
||||||
char _value[0];
|
char _value[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct oprogram : public object
|
struct oprogram : public object {
|
||||||
{
|
// oprogram may first have been allocated with len+1 bytes
|
||||||
// oprogram may first have been allocated with len+1 bytes
|
void set(const char* value, unsigned int len) {
|
||||||
void set(const char* value, unsigned int len)
|
_type = cmd_program;
|
||||||
{
|
if (value != NULL) {
|
||||||
_type = cmd_program;
|
if (len > 0) (void)memcpy(_value, value, len);
|
||||||
if (value != NULL)
|
_value[len] = 0;
|
||||||
{
|
_len = len;
|
||||||
if (len>0)
|
} else {
|
||||||
(void)memcpy(_value, value, len);
|
_value[0] = 0;
|
||||||
_value[len] = 0;
|
_len = 0;
|
||||||
_len = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_value[0] = 0;
|
|
||||||
_len = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// length of _value, not includiong the terminal '\0'
|
// length of _value, not includiong the terminal '\0'
|
||||||
unsigned int _len;
|
unsigned int _len;
|
||||||
char _value[0];
|
char _value[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symbol : public object
|
struct symbol : public object {
|
||||||
{
|
// symbol may first have been allocated with len+1 bytes
|
||||||
// symbol may first have been allocated with len+1 bytes
|
void set(const char* value, unsigned int len, bool auto_eval) {
|
||||||
void set(const char* value, unsigned int len, bool auto_eval)
|
_type = cmd_symbol;
|
||||||
{
|
_auto_eval = auto_eval;
|
||||||
_type = cmd_symbol;
|
|
||||||
_auto_eval = auto_eval;
|
|
||||||
|
|
||||||
if (value != NULL)
|
if (value != NULL) {
|
||||||
{
|
if (len > 0) (void)memcpy(_value, value, len);
|
||||||
if (len>0)
|
_value[len] = 0;
|
||||||
(void)memcpy(_value, value, len);
|
_len = len;
|
||||||
_value[len] = 0;
|
} else {
|
||||||
_len = len;
|
_value[0] = 0;
|
||||||
}
|
_len = 0;
|
||||||
else
|
|
||||||
{
|
|
||||||
_value[0] = 0;
|
|
||||||
_len = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
bool _auto_eval;
|
bool _auto_eval;
|
||||||
// length of _value, not includiong the terminal '\0'
|
// length of _value, not includiong the terminal '\0'
|
||||||
unsigned int _len;
|
unsigned int _len;
|
||||||
char _value[0];
|
char _value[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct keyword : public object
|
struct keyword : public object {
|
||||||
{
|
// keyword may first have been allocated with len+1 bytes
|
||||||
// keyword may first have been allocated with len+1 bytes
|
void set(program_fn_t fn, const char* value, unsigned int len) {
|
||||||
void set(program_fn_t fn, const char* value, unsigned int len)
|
_type = cmd_keyword;
|
||||||
{
|
_fn = fn;
|
||||||
_type = cmd_keyword;
|
if (value != NULL) {
|
||||||
_fn = fn;
|
if (len > 0) (void)memcpy(_value, value, len);
|
||||||
if (value != NULL)
|
_value[len] = 0;
|
||||||
{
|
_len = len;
|
||||||
if (len>0)
|
} else {
|
||||||
(void)memcpy(_value, value, len);
|
_value[0] = 0;
|
||||||
_value[len] = 0;
|
_len = 0;
|
||||||
_len = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_value[0] = 0;
|
|
||||||
_len = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
program_fn_t _fn;
|
program_fn_t _fn;
|
||||||
// length of _value, not includiong the terminal '\0'
|
// length of _value, not includiong the terminal '\0'
|
||||||
unsigned int _len;
|
unsigned int _len;
|
||||||
char _value[0];
|
char _value[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct branch : public object
|
struct branch : public object {
|
||||||
{
|
//
|
||||||
//
|
void set(branch_fn_t fn, const char* value, unsigned int len) {
|
||||||
void set(branch_fn_t fn, const char* value, unsigned int len)
|
_type = cmd_branch;
|
||||||
{
|
_fn = fn;
|
||||||
_type = cmd_branch;
|
arg1 = -1;
|
||||||
_fn = fn;
|
arg2 = -1;
|
||||||
arg1 = -1;
|
arg3 = -1;
|
||||||
arg2 = -1;
|
farg1 = NULL;
|
||||||
arg3 = -1;
|
farg2 = NULL;
|
||||||
farg1 = NULL;
|
arg_bool = 0;
|
||||||
farg2 = NULL;
|
if (value != NULL) {
|
||||||
arg_bool = 0;
|
if (len > 0) (void)memcpy(_value, value, len);
|
||||||
if (value != NULL)
|
_value[len] = 0;
|
||||||
{
|
_len = len;
|
||||||
if (len>0)
|
} else {
|
||||||
(void)memcpy(_value, value, len);
|
_value[0] = 0;
|
||||||
_value[len] = 0;
|
_len = 0;
|
||||||
_len = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_value[0] = 0;
|
|
||||||
_len = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// branch function
|
// branch function
|
||||||
branch_fn_t _fn;
|
branch_fn_t _fn;
|
||||||
// args used by cmd_branch cmds
|
// args used by cmd_branch cmds
|
||||||
int arg1, arg2, arg3;
|
int arg1, arg2, arg3;
|
||||||
number *farg1, *farg2;
|
number *farg1, *farg2;
|
||||||
bool arg_bool;
|
bool arg_bool;
|
||||||
|
|
||||||
// length of _value, not includiong the terminal '\0'
|
// length of _value, not includiong the terminal '\0'
|
||||||
unsigned int _len;
|
unsigned int _len;
|
||||||
char _value[0];
|
char _value[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
1055
src/parse.hpp
1055
src/parse.hpp
File diff suppressed because it is too large
Load diff
402
src/program.cpp
402
src/program.cpp
|
@ -4,194 +4,244 @@
|
||||||
const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS;
|
const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS;
|
||||||
|
|
||||||
//
|
//
|
||||||
program::keyword_t program::s_keywords[] =
|
program::keyword_t program::s_keywords[] = {
|
||||||
{
|
// GENERAL
|
||||||
//GENERAL
|
{cmd_undef, "", NULL, "\nGENERAL"},
|
||||||
{ cmd_undef, "", NULL, "\nGENERAL"},
|
{cmd_keyword, "nop", &program::rpn_nop, "no operation"},
|
||||||
{ cmd_keyword, "nop", &program::rpn_nop, "no operation"},
|
{cmd_keyword, "help", &program::rpn_help, "this help message"},
|
||||||
{ cmd_keyword, "help", &program::rpn_help, "this help message" },
|
{cmd_keyword, "h", &program::rpn_help, ""},
|
||||||
{ cmd_keyword, "h", &program::rpn_help, "" },
|
{cmd_keyword, "?", &program::rpn_help, ""},
|
||||||
{ cmd_keyword, "?", &program::rpn_help, "" },
|
{cmd_keyword, "quit", &program::rpn_good_bye, "quit software"},
|
||||||
{ cmd_keyword, "quit", &program::rpn_good_bye, "quit software" },
|
{cmd_keyword, "q", &program::rpn_good_bye, ""},
|
||||||
{ cmd_keyword, "q", &program::rpn_good_bye, "" },
|
{cmd_keyword, "exit", &program::rpn_good_bye, ""},
|
||||||
{ cmd_keyword, "exit", &program::rpn_good_bye, "" },
|
{cmd_keyword, "test", &program::rpn_test, ""}, // not seen by user
|
||||||
{ cmd_keyword, "test", &program::rpn_test, "" }, //not seen by user
|
{cmd_keyword, "version", &program::rpn_version, "show rpn version"},
|
||||||
{ cmd_keyword, "version", &program::rpn_version, "show rpn version" },
|
{cmd_keyword, "uname", &program::rpn_uname,
|
||||||
{ cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string" },
|
"show rpn complete identification string"},
|
||||||
{ cmd_keyword, "history", &program::rpn_history, "see commands history" },
|
{cmd_keyword, "history", &program::rpn_history, "see commands history"},
|
||||||
|
|
||||||
//USUAL OPERATIONS ON REALS AND COMPLEXES
|
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||||
{ cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
{cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||||
{ cmd_keyword, "+", &program::rpn_plus, "addition" },
|
{cmd_keyword, "+", &program::rpn_plus, "addition"},
|
||||||
{ cmd_keyword, "-", &program::rpn_minus, "substraction" },
|
{cmd_keyword, "-", &program::rpn_minus, "substraction"},
|
||||||
{ cmd_keyword, "chs", &program::rpn_neg , "negation" },
|
{cmd_keyword, "chs", &program::rpn_neg, "negation"},
|
||||||
{ cmd_keyword, "neg", &program::rpn_neg , "" },
|
{cmd_keyword, "neg", &program::rpn_neg, ""},
|
||||||
{ cmd_keyword, "*", &program::rpn_mul, "multiplication" },
|
{cmd_keyword, "*", &program::rpn_mul, "multiplication"},
|
||||||
{ cmd_keyword, "/", &program::rpn_div, "division" },
|
{cmd_keyword, "/", &program::rpn_div, "division"},
|
||||||
{ cmd_keyword, "inv", &program::rpn_inv, "inverse" },
|
{cmd_keyword, "inv", &program::rpn_inv, "inverse"},
|
||||||
{ cmd_keyword, "^", &program::rpn_power, "power" },
|
{cmd_keyword, "^", &program::rpn_power, "power"},
|
||||||
{ cmd_keyword, "pow", &program::rpn_power, "" },
|
{cmd_keyword, "pow", &program::rpn_power, ""},
|
||||||
{ cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root" },
|
{cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
|
||||||
{ cmd_keyword, "sq", &program::rpn_square, "rpn_square" },
|
{cmd_keyword, "sq", &program::rpn_square, "rpn_square"},
|
||||||
{ cmd_keyword, "sqr", &program::rpn_square, "" },
|
{cmd_keyword, "sqr", &program::rpn_square, ""},
|
||||||
{ cmd_keyword, "abs", &program::rpn_abs, "absolute value" },
|
{cmd_keyword, "abs", &program::rpn_abs, "absolute value"},
|
||||||
{ cmd_keyword, "dec", &program::rpn_dec, "decimal representation" },
|
{cmd_keyword, "dec", &program::rpn_dec, "decimal representation"},
|
||||||
{ cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation" },
|
{cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"},
|
||||||
{ cmd_keyword, "bin", &program::rpn_bin, "decimal representation" },
|
{cmd_keyword, "bin", &program::rpn_bin, "decimal representation"},
|
||||||
{ cmd_keyword, "base", &program::rpn_base, "arbitrary base representation" },
|
{cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"},
|
||||||
{ cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0" },
|
{cmd_keyword, "sign", &program::rpn_sign,
|
||||||
|
"1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"},
|
||||||
|
|
||||||
//OPERATIONS ON REALS
|
// OPERATIONS ON REALS
|
||||||
{ cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
|
{cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
|
||||||
{ cmd_keyword, "%", &program::rpn_purcent, "purcent" },
|
{cmd_keyword, "%", &program::rpn_purcent, "purcent"},
|
||||||
{ cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent" },
|
{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
|
||||||
{ cmd_keyword, "mod", &program::rpn_modulo, "modulo" },
|
{cmd_keyword, "mod", &program::rpn_modulo, "modulo"},
|
||||||
{ cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x" },
|
{cmd_keyword, "fact", &program::rpn_fact,
|
||||||
{ cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number" },
|
"n! for integer n or Gamma(x+1) for fractional x"},
|
||||||
{ cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number" },
|
{cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"},
|
||||||
{ cmd_keyword, "floor", &program::rpn_floor, "largest number <=" },
|
{cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
|
||||||
{ cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >=" },
|
{cmd_keyword, "floor", &program::rpn_floor, "largest number <="},
|
||||||
{ cmd_keyword, "ip", &program::rpn_ip, "integer part" },
|
{cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="},
|
||||||
{ cmd_keyword, "fp", &program::rpn_fp, "fractional part" },
|
{cmd_keyword, "ip", &program::rpn_ip, "integer part"},
|
||||||
{ cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers" },
|
{cmd_keyword, "fp", &program::rpn_fp, "fractional part"},
|
||||||
{ cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers" },
|
{cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"},
|
||||||
|
{cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"},
|
||||||
|
|
||||||
//nOPERATIONS ON COMPLEXES
|
// nOPERATIONS ON COMPLEXES
|
||||||
{ cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
|
{cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
|
||||||
{ cmd_keyword, "re", &program::rpn_re, "complex real part" },
|
{cmd_keyword, "re", &program::rpn_re, "complex real part"},
|
||||||
{ cmd_keyword, "im", &program::rpn_im, "complex imaginary part" },
|
{cmd_keyword, "im", &program::rpn_im, "complex imaginary part"},
|
||||||
{ cmd_keyword, "conj", &program::rpn_conj, "complex conjugate" },
|
{cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"},
|
||||||
{ cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians" },
|
{cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"},
|
||||||
{ cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals" },
|
{cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"},
|
||||||
{ cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex" },
|
{cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
|
||||||
{ cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar" },
|
{cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
|
||||||
{ cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian" },
|
{cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
|
||||||
|
|
||||||
//MODE
|
// MODE
|
||||||
{ cmd_undef, "", NULL, "\nMODE"},
|
{cmd_undef, "", NULL, "\nMODE"},
|
||||||
{ cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std" },
|
{cmd_keyword, "std", &program::rpn_std,
|
||||||
{ cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix" },
|
"standard floating numbers representation. ex: std"},
|
||||||
{ cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci" },
|
{cmd_keyword, "fix", &program::rpn_fix,
|
||||||
{ cmd_keyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec" },
|
"fixed point representation. ex: 6 fix"},
|
||||||
{ cmd_keyword, "round", &program::rpn_round, "set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward +inf\", \"toward -inf\", \"away from zero\"] round" },
|
{cmd_keyword, "sci", &program::rpn_sci,
|
||||||
{ cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default" },
|
"scientific floating point representation. ex: 20 sci"},
|
||||||
{ cmd_keyword, "type", &program::rpn_type, "show type of stack first entry" },
|
{cmd_keyword, "prec", &program::rpn_precision,
|
||||||
|
"set float precision in bits. ex: 256 prec"},
|
||||||
|
{cmd_keyword, "round", &program::rpn_round,
|
||||||
|
"set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward "
|
||||||
|
"+inf\", \"toward -inf\", \"away from zero\"] round"},
|
||||||
|
{cmd_keyword, "default", &program::rpn_default,
|
||||||
|
"set float representation and precision to default"},
|
||||||
|
{cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"},
|
||||||
|
|
||||||
//TESTS
|
// TESTS
|
||||||
{ cmd_undef, "", NULL, "\nTEST"},
|
{cmd_undef, "", NULL, "\nTEST"},
|
||||||
{ cmd_keyword, ">", &program::rpn_sup, "binary operator >" },
|
{cmd_keyword, ">", &program::rpn_sup, "binary operator >"},
|
||||||
{ cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >=" },
|
{cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="},
|
||||||
{ cmd_keyword, "<", &program::rpn_inf, "binary operator <" },
|
{cmd_keyword, "<", &program::rpn_inf, "binary operator <"},
|
||||||
{ cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <=" },
|
{cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="},
|
||||||
{ cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)" },
|
{cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"},
|
||||||
{ cmd_keyword, "==", &program::rpn_eq , "binary operator == (equal)" },
|
{cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"},
|
||||||
{ cmd_keyword, "and", &program::rpn_test_and , "boolean operator and" },
|
{cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"},
|
||||||
{ cmd_keyword, "or", &program::rpn_test_or , "boolean operator or" },
|
{cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"},
|
||||||
{ cmd_keyword, "xor", &program::rpn_test_xor , "boolean operator xor" },
|
{cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
|
||||||
{ cmd_keyword, "not", &program::rpn_test_not , "boolean operator not" },
|
{cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"},
|
||||||
{ cmd_keyword, "same", &program::rpn_same , "boolean operator same (equal)" },
|
{cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"},
|
||||||
|
|
||||||
//STACK
|
// STACK
|
||||||
{ cmd_undef, "", NULL, "\nSTACK"},
|
{cmd_undef, "", NULL, "\nSTACK"},
|
||||||
{ cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries" },
|
{cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
|
||||||
{ cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry" },
|
{cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"},
|
||||||
{ cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries" },
|
{cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"},
|
||||||
{ cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries" },
|
{cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries"},
|
||||||
{ cmd_keyword, "del", &program::rpn_erase, "drop all stack entries" },
|
{cmd_keyword, "del", &program::rpn_erase, "drop all stack entries"},
|
||||||
{ cmd_keyword, "erase", &program::rpn_erase, "" },
|
{cmd_keyword, "erase", &program::rpn_erase, ""},
|
||||||
{ cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries" },
|
{cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
|
||||||
{ cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry" },
|
{cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
|
||||||
{ cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries" },
|
{cmd_keyword, "dup2", &program::rpn_dup2,
|
||||||
{ cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries" },
|
"duplicate 2 first stack entries"},
|
||||||
{ cmd_keyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack" },
|
{cmd_keyword, "dupn", &program::rpn_dupn,
|
||||||
{ cmd_keyword, "depth", &program::rpn_depth, "give stack depth" },
|
"duplicate n first stack entries"},
|
||||||
{ cmd_keyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack" },
|
{cmd_keyword, "pick", &program::rpn_pick,
|
||||||
{ cmd_keyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position" },
|
"push a copy of the given stack level onto the stack"},
|
||||||
{ cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack" },
|
{cmd_keyword, "depth", &program::rpn_depth, "give stack depth"},
|
||||||
|
{cmd_keyword, "roll", &program::rpn_roll,
|
||||||
|
"move a stack entry to the top of the stack"},
|
||||||
|
{cmd_keyword, "rolld", &program::rpn_rolld,
|
||||||
|
"move the element on top of the stack to a higher stack position"},
|
||||||
|
{cmd_keyword, "over", &program::rpn_over,
|
||||||
|
"push a copy of the element in stack level 2 onto the stack"},
|
||||||
|
|
||||||
//STRING
|
// STRING
|
||||||
{ cmd_undef, "", NULL, "\nSTRING"},
|
{cmd_undef, "", NULL, "\nSTRING"},
|
||||||
{ cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string" },
|
{cmd_keyword, "->str", &program::rpn_instr,
|
||||||
{ cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object" },
|
"convert an object into a string"},
|
||||||
{ cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string" },
|
{cmd_keyword, "str->", &program::rpn_strout,
|
||||||
{ cmd_keyword, "num", &program::rpn_num, "return ASCII code of the first character of the string in stack level 1 as a real number" },
|
"convert a string into an object"},
|
||||||
{ cmd_keyword, "size", &program::rpn_strsize, "return the length of the string" },
|
{cmd_keyword, "chr", &program::rpn_chr,
|
||||||
{ cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2" },
|
"convert ASCII character code in stack level 1 into a string"},
|
||||||
{ cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3" },
|
{cmd_keyword, "num", &program::rpn_num,
|
||||||
|
"return ASCII code of the first character of the string in stack level 1 "
|
||||||
|
"as a real number"},
|
||||||
|
{cmd_keyword, "size", &program::rpn_strsize,
|
||||||
|
"return the length of the string"},
|
||||||
|
{cmd_keyword, "pos", &program::rpn_strpos,
|
||||||
|
"seach for the string in level 1 within the string in level 2"},
|
||||||
|
{cmd_keyword, "sub", &program::rpn_strsub,
|
||||||
|
"return a substring of the string in level 3"},
|
||||||
|
|
||||||
//BRANCH
|
// BRANCH
|
||||||
{ cmd_undef, "", NULL, "\nBRANCH"},
|
{cmd_undef, "", NULL, "\nBRANCH"},
|
||||||
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "if <test-instruction> then <true-instructions> else <false-instructions> end" },
|
{cmd_branch, "if", (program_fn_t)&program::rpn_if,
|
||||||
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if" },
|
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
||||||
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" },
|
"end"},
|
||||||
{ cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" },
|
{cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"},
|
||||||
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step" },
|
{cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"},
|
||||||
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "<start> <end> for <variable> <instructions> next|<step> step" },
|
{cmd_branch, "end", (program_fn_t)&program::rpn_end,
|
||||||
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" },
|
"used with various branch instructions"},
|
||||||
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for" },
|
{cmd_branch, "start", (program_fn_t)&program::rpn_start,
|
||||||
{ cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, <test-instruction> <true-instruction> ift" },
|
"<start> <end> start <instructions> next|<step> step"},
|
||||||
{ cmd_keyword, "ifte",&program::rpn_ifte, "similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte" },
|
{cmd_branch, "for", (program_fn_t)&program::rpn_for,
|
||||||
{ cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end" },
|
"<start> <end> for <variable> <instructions> next|<step> step"},
|
||||||
{ cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do" },
|
{cmd_branch, "next", (program_fn_t)&program::rpn_next,
|
||||||
{ cmd_branch, "unti", (program_fn_t)&program::rpn_until, "" },
|
"used with start and for"},
|
||||||
{ cmd_branch, "while", (program_fn_t)&program::rpn_while, "while <test-instruction> repeat <loop-instructions> end" },
|
{cmd_branch, "step", (program_fn_t)&program::rpn_step,
|
||||||
{ cmd_branch, "whil", (program_fn_t)&program::rpn_while, "" },
|
"used with start and for"},
|
||||||
{ cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while" },
|
{cmd_keyword, "ift", &program::rpn_ift,
|
||||||
{ cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, "" },
|
"similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||||
|
{cmd_keyword, "ifte", &program::rpn_ifte,
|
||||||
|
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
||||||
|
"<false-instruction> ifte"},
|
||||||
|
{cmd_branch, "do", (program_fn_t)&program::rpn_do,
|
||||||
|
"do <instructions> until <condition> end"},
|
||||||
|
{cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"},
|
||||||
|
{cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""},
|
||||||
|
{cmd_branch, "while", (program_fn_t)&program::rpn_while,
|
||||||
|
"while <test-instruction> repeat <loop-instructions> end"},
|
||||||
|
{cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""},
|
||||||
|
{cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat,
|
||||||
|
"used with while"},
|
||||||
|
{cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""},
|
||||||
|
|
||||||
//STORE
|
// STORE
|
||||||
{ cmd_undef, "", NULL, "\nSTORE"},
|
{cmd_undef, "", NULL, "\nSTORE"},
|
||||||
{ cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto" },
|
{cmd_keyword, "sto", &program::rpn_sto,
|
||||||
{ cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl" },
|
"store a variable. ex: 1 'name' sto"},
|
||||||
{ cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge" },
|
{cmd_keyword, "rcl", &program::rpn_rcl,
|
||||||
{ cmd_keyword, "vars", &program::rpn_vars, "list all variables" },
|
"recall a variable. ex: 'name' rcl"},
|
||||||
{ cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables" },
|
{cmd_keyword, "purge", &program::rpn_purge,
|
||||||
{ cmd_keyword, "edit", &program::rpn_edit, "edit a variable content" },
|
"delete a variable. ex: 'name' purge"},
|
||||||
{ cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+" },
|
{cmd_keyword, "vars", &program::rpn_vars, "list all variables"},
|
||||||
{ cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-" },
|
{cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"},
|
||||||
{ cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*" },
|
{cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"},
|
||||||
{ cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/" },
|
{cmd_keyword, "sto+", &program::rpn_stoadd,
|
||||||
{ cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg" },
|
"add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||||
{ cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv" },
|
{cmd_keyword, "sto-", &program::rpn_stosub,
|
||||||
|
"substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||||
|
{cmd_keyword, "sto*", &program::rpn_stomul,
|
||||||
|
"multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||||
|
{cmd_keyword, "sto/", &program::rpn_stodiv,
|
||||||
|
"divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||||
|
{cmd_keyword, "sneg", &program::rpn_stoneg,
|
||||||
|
"negate a variable. ex: 'name' sneg"},
|
||||||
|
{cmd_keyword, "sinv", &program::rpn_stoinv,
|
||||||
|
"inverse a variable. ex: 1 'name' sinv"},
|
||||||
|
|
||||||
//PROGRAM
|
// PROGRAM
|
||||||
{ cmd_undef, "", NULL, "\nPROGRAM"},
|
{cmd_undef, "", NULL, "\nPROGRAM"},
|
||||||
{ cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" },
|
{cmd_keyword, "eval", &program::rpn_eval,
|
||||||
{ cmd_branch, "->", (program_fn_t)&program::rpn_inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> >>" },
|
"evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||||
|
{cmd_branch, "->", (program_fn_t)&program::rpn_inprog,
|
||||||
|
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
||||||
|
">>"},
|
||||||
|
|
||||||
//TRIG ON REALS AND COMPLEXES
|
// TRIG ON REALS AND COMPLEXES
|
||||||
{ cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
|
{cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
|
||||||
{ cmd_keyword, "pi", &program::rpn_pi, "pi constant" },
|
{cmd_keyword, "pi", &program::rpn_pi, "pi constant"},
|
||||||
{ cmd_keyword, "sin", &program::rpn_sin, "sinus" },
|
{cmd_keyword, "sin", &program::rpn_sin, "sinus"},
|
||||||
{ cmd_keyword, "asin", &program::rpn_asin, "arg sinus" },
|
{cmd_keyword, "asin", &program::rpn_asin, "arg sinus"},
|
||||||
{ cmd_keyword, "cos", &program::rpn_cos , "cosinus" },
|
{cmd_keyword, "cos", &program::rpn_cos, "cosinus"},
|
||||||
{ cmd_keyword, "acos", &program::rpn_acos, "arg cosinus" },
|
{cmd_keyword, "acos", &program::rpn_acos, "arg cosinus"},
|
||||||
{ cmd_keyword, "tan", &program::rpn_tan, "tangent" },
|
{cmd_keyword, "tan", &program::rpn_tan, "tangent"},
|
||||||
{ cmd_keyword, "atan", &program::rpn_atan, "arg tangent" },
|
{cmd_keyword, "atan", &program::rpn_atan, "arg tangent"},
|
||||||
{ cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians" },
|
{cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
|
||||||
{ cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees" },
|
{cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
|
||||||
|
|
||||||
//LOGS ON REALS AND COMPLEXES
|
// LOGS ON REALS AND COMPLEXES
|
||||||
{ cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
|
{cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
|
||||||
{ cmd_keyword, "e", &program::rpn_e, "Euler constant" },
|
{cmd_keyword, "e", &program::rpn_e, "Euler constant"},
|
||||||
{ cmd_keyword, "ln", &program::rpn_ln, "logarithm base e" },
|
{cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"},
|
||||||
{ cmd_keyword, "log", &program::rpn_ln, "" },
|
{cmd_keyword, "log", &program::rpn_ln, ""},
|
||||||
{ cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0" },
|
{cmd_keyword, "lnp1", &program::rpn_lnp1,
|
||||||
{ cmd_keyword, "exp", &program::rpn_exp, "exponential" },
|
"ln(1+x) which is useful when x is close to 0"},
|
||||||
{ cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0" },
|
{cmd_keyword, "exp", &program::rpn_exp, "exponential"},
|
||||||
{ cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10" },
|
{cmd_keyword, "expm", &program::rpn_expm,
|
||||||
{ cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10" },
|
"exp(x)-1 which is useful when x is close to 0"},
|
||||||
{ cmd_keyword, "exp10", &program::rpn_alog10, "" },
|
{cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"},
|
||||||
{ cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2" },
|
{cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"},
|
||||||
{ cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2" },
|
{cmd_keyword, "exp10", &program::rpn_alog10, ""},
|
||||||
{ cmd_keyword, "exp2", &program::rpn_alog2, "" },
|
{cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"},
|
||||||
{ cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine" },
|
{cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"},
|
||||||
{ cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine" },
|
{cmd_keyword, "exp2", &program::rpn_alog2, ""},
|
||||||
{ cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine" },
|
{cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
|
||||||
{ cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine" },
|
{cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
|
||||||
{ cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent" },
|
{cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine"},
|
||||||
{ cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent" },
|
{cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"},
|
||||||
|
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
||||||
|
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
|
||||||
|
|
||||||
// end
|
// end
|
||||||
{ cmd_max, "", NULL, "" },
|
{cmd_max, "", NULL, ""},
|
||||||
};
|
};
|
||||||
|
|
1009
src/program.hpp
1009
src/program.hpp
File diff suppressed because it is too large
Load diff
|
@ -1,309 +1,285 @@
|
||||||
//
|
//
|
||||||
int rpn_if(branch& myobj)
|
int rpn_if(branch& myobj) {
|
||||||
{
|
// myobj.arg1 = 'if' condition evaluation value
|
||||||
// myobj.arg1 = 'if' condition evaluation value
|
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
|
||||||
|
|
||||||
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
|
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
|
||||||
myobj.arg1 = 1;
|
myobj.arg1 = 1;
|
||||||
else
|
else
|
||||||
myobj.arg1 = 0;
|
myobj.arg1 = 0;
|
||||||
(void)_stack->pop_back();
|
(void)_stack->pop_back();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_then(branch& myobj)
|
int rpn_then(branch& myobj) {
|
||||||
{
|
// myobj.arg1 = index of then + 1
|
||||||
// myobj.arg1 = index of then + 1
|
// myobj.arg2 = index of else + 1 or end + 1
|
||||||
// myobj.arg2 = index of else + 1 or end + 1
|
// myobj.arg3 = index of if
|
||||||
// myobj.arg3 = index of if
|
// if condition is true -> arg1 (= jump to then + 1)
|
||||||
// if condition is true -> arg1 (= jump to then + 1)
|
// else -> arg2 (= jump to else + 1 or end + 1)
|
||||||
// else -> arg2 (= jump to else + 1 or end + 1)
|
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
if (if_cmd->arg1 == 1)
|
||||||
if (if_cmd->arg1 == 1)
|
return myobj.arg1;
|
||||||
return myobj.arg1;
|
else
|
||||||
else
|
return myobj.arg2;
|
||||||
return myobj.arg2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_else(branch& myobj)
|
int rpn_else(branch& myobj) {
|
||||||
{
|
// myobj.arg1 = index of else + 1
|
||||||
// myobj.arg1 = index of else + 1
|
// myobj.arg2 = index of end + 1
|
||||||
// myobj.arg2 = index of end + 1
|
// myobj.arg3 = index of if
|
||||||
// myobj.arg3 = index of if
|
// if condition was false -> arg1 (= jump to else + 1)
|
||||||
// if condition was false -> arg1 (= jump to else + 1)
|
// if condition was true -> arg2 (= jump to end + 1)
|
||||||
// if condition was true -> arg2 (= jump to end + 1)
|
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
if (if_cmd->arg1 == 1)
|
||||||
if (if_cmd->arg1 == 1)
|
return myobj.arg2;
|
||||||
return myobj.arg2;
|
else
|
||||||
else
|
return myobj.arg1;
|
||||||
return myobj.arg1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_end(branch& myobj)
|
int rpn_end(branch& myobj) {
|
||||||
{
|
int ret = -1;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
// arg1 = index of do+1 in case of do..unti..end
|
|
||||||
if (myobj.arg1 != -1)
|
|
||||||
{
|
|
||||||
// in a template do..unti..end
|
|
||||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
|
||||||
|
|
||||||
// check arg
|
|
||||||
number* arg = (number*)_stack->pop_back();
|
|
||||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
|
|
||||||
ret = myobj.arg1;
|
|
||||||
}
|
|
||||||
// arg2 = index of while+1 in case of while..repeat..end
|
|
||||||
else if (myobj.arg2 != -1)
|
|
||||||
ret = myobj.arg2;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rpn_do(branch& myobj)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rpn_until(branch& myobj)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
void rpn_ift(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
|
|
||||||
// check ift arg
|
|
||||||
// arg is true if number != 0 or if is nan or +/-inf
|
|
||||||
number* testee = ((number*)_stack->get_obj(1));
|
|
||||||
|
|
||||||
if (!mpfr_zero_p(testee->_value.mpfr))
|
|
||||||
{
|
|
||||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
|
|
||||||
(void)_stack->pop_back(2);
|
|
||||||
|
|
||||||
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
|
|
||||||
(void)_calc_stack.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
(void)_stack->pop_back(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_ifte(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(3);
|
|
||||||
ARG_MUST_BE_OF_TYPE(2, cmd_number);
|
|
||||||
|
|
||||||
// check ifte arg
|
|
||||||
// arg is true if number != 0 or if is nan or +/-inf
|
|
||||||
number* testee = ((number*)_stack->get_obj(2));
|
|
||||||
|
|
||||||
if (!mpfr_zero_p(testee->_value.mpfr))
|
|
||||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack));
|
|
||||||
else
|
|
||||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
|
|
||||||
|
|
||||||
(void)_stack->pop_back(3);
|
|
||||||
|
|
||||||
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
|
|
||||||
(void)_calc_stack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
int rpn_while(branch& myobj)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rpn_repeat(branch& myobj)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
|
// arg1 = index of do+1 in case of do..unti..end
|
||||||
|
if (myobj.arg1 != -1) {
|
||||||
|
// in a template do..unti..end
|
||||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
|
|
||||||
// check arg
|
// check arg
|
||||||
// myobj.arg1 is end+1
|
|
||||||
number* arg = (number*)_stack->pop_back();
|
number* arg = (number*)_stack->pop_back();
|
||||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
|
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
|
||||||
ret = myobj.arg1;
|
}
|
||||||
|
// arg2 = index of while+1 in case of while..repeat..end
|
||||||
|
else if (myobj.arg2 != -1)
|
||||||
|
ret = myobj.arg2;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_start(branch& myobj)
|
int rpn_do(branch& myobj) {
|
||||||
{
|
// nothing
|
||||||
int ret = -1;
|
return -1;
|
||||||
|
|
||||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
|
||||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
|
||||||
|
|
||||||
// farg2 = last value of start command
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
myobj.farg2 = (number*)_calc_stack.back();
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
// farg1 = first value of start command
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
myobj.farg1 = (number*)_calc_stack.back();
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
// test value
|
|
||||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
|
||||||
// last boundary lower than first boundary
|
|
||||||
// -> next command shall be after 'next'
|
|
||||||
// arg2 holds index of 'next'
|
|
||||||
ret = myobj.arg2 + 1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_for(branch& myobj)
|
int rpn_until(branch& myobj) {
|
||||||
{
|
// nothing
|
||||||
int ret;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
//
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
void rpn_ift(void) {
|
||||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
MIN_ARGUMENTS(2);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
|
|
||||||
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
|
// check ift arg
|
||||||
|
// arg is true if number != 0 or if is nan or +/-inf
|
||||||
|
number* testee = ((number*)_stack->get_obj(1));
|
||||||
|
|
||||||
// farg2 = last value of for command
|
if (!mpfr_zero_p(testee->_value.mpfr)) {
|
||||||
// arg1 = index of symbol to increase
|
CHECK_MPFR(
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
|
||||||
myobj.farg2 = (number*)_calc_stack.back();
|
(void)_stack->pop_back(2);
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
// farg1 = first value of for command
|
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1,
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
*_stack));
|
||||||
myobj.farg1 = (number*)_calc_stack.back();
|
(void)_calc_stack.pop_back();
|
||||||
_stack->pop_back();
|
} else
|
||||||
|
(void)_stack->pop_back(2);
|
||||||
|
}
|
||||||
|
|
||||||
// test value
|
void rpn_ifte(void) {
|
||||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
MIN_ARGUMENTS(3);
|
||||||
// last boundary lower than first boundary
|
ARG_MUST_BE_OF_TYPE(2, cmd_number);
|
||||||
// -> next command shall be after 'next'
|
|
||||||
// arg2 holds index of 'next'
|
// check ifte arg
|
||||||
ret = myobj.arg2 + 1;
|
// arg is true if number != 0 or if is nan or +/-inf
|
||||||
|
number* testee = ((number*)_stack->get_obj(2));
|
||||||
|
|
||||||
|
if (!mpfr_zero_p(testee->_value.mpfr))
|
||||||
|
CHECK_MPFR(
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack));
|
||||||
|
else
|
||||||
|
CHECK_MPFR(
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
|
||||||
|
|
||||||
|
(void)_stack->pop_back(3);
|
||||||
|
|
||||||
|
CHECK_MPFR(
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack));
|
||||||
|
(void)_calc_stack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
int rpn_while(branch& myobj) {
|
||||||
|
// nothing
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rpn_repeat(branch& myobj) {
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
|
|
||||||
|
// check arg
|
||||||
|
// myobj.arg1 is end+1
|
||||||
|
number* arg = (number*)_stack->pop_back();
|
||||||
|
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rpn_start(branch& myobj) {
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||||
|
|
||||||
|
// farg2 = last value of start command
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
myobj.farg2 = (number*)_calc_stack.back();
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
// farg1 = first value of start command
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
myobj.farg1 = (number*)_calc_stack.back();
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
// test value
|
||||||
|
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||||
|
// last boundary lower than first boundary
|
||||||
|
// -> next command shall be after 'next'
|
||||||
|
// arg2 holds index of 'next'
|
||||||
|
ret = myobj.arg2 + 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rpn_for(branch& myobj) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||||
|
|
||||||
|
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
|
||||||
|
|
||||||
|
// farg2 = last value of for command
|
||||||
|
// arg1 = index of symbol to increase
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
myobj.farg2 = (number*)_calc_stack.back();
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
// farg1 = first value of for command
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
myobj.farg1 = (number*)_calc_stack.back();
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
// test value
|
||||||
|
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||||
|
// last boundary lower than first boundary
|
||||||
|
// -> next command shall be after 'next'
|
||||||
|
// arg2 holds index of 'next'
|
||||||
|
ret = myobj.arg2 + 1;
|
||||||
|
else {
|
||||||
|
// store symbol with first value
|
||||||
|
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
|
||||||
|
ret = myobj.arg1 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rpn_next(branch& myobj) {
|
||||||
|
// arg1 = index of start or for command in program
|
||||||
|
// farg1 = current count
|
||||||
|
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
||||||
|
if (!myobj.arg_bool) {
|
||||||
|
myobj.arg_bool = true;
|
||||||
|
myobj.farg1 = start_or_for->farg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment then test
|
||||||
|
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL,
|
||||||
|
MPFR_DEFAULT_RND);
|
||||||
|
|
||||||
|
// for command: increment symbol too
|
||||||
|
if (start_or_for->arg1 != -1) {
|
||||||
|
object* obj;
|
||||||
|
unsigned int size;
|
||||||
|
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||||
|
|
||||||
|
// increase symbol variable
|
||||||
|
_local_heap.replace_value(string(var->_value), myobj.farg1,
|
||||||
|
myobj.farg1->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// test value
|
||||||
|
if (myobj.farg1->_value > start_or_for->farg2->_value) {
|
||||||
|
// end of loop
|
||||||
|
myobj.arg_bool = false; // init again next time
|
||||||
|
_calc_stack.pop_back(2);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
// for command: next instruction will be after symbol variable
|
||||||
|
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
|
||||||
|
// start command: next instruction will be after start command
|
||||||
else
|
else
|
||||||
{
|
return myobj.arg1 + 1;
|
||||||
// store symbol with first value
|
}
|
||||||
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
|
|
||||||
ret = myobj.arg1 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_next(branch& myobj)
|
int rpn_step(branch& myobj) {
|
||||||
{
|
int ret;
|
||||||
|
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||||
|
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||||
|
|
||||||
|
number* step = (number*)_stack->pop_back();
|
||||||
|
|
||||||
|
// end of loop if step is negative or zero
|
||||||
|
if (mpfr_cmp_d(step->_value.mpfr, 0.0) <= 0)
|
||||||
|
ret = -1;
|
||||||
|
else {
|
||||||
// arg1 = index of start or for command in program
|
// arg1 = index of start or for command in program
|
||||||
// farg1 = current count
|
// farg1 = current count
|
||||||
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
||||||
if (! myobj.arg_bool)
|
if (!myobj.arg_bool) {
|
||||||
{
|
myobj.arg_bool = true;
|
||||||
myobj.arg_bool = true;
|
myobj.farg1 = start_or_for->farg1;
|
||||||
myobj.farg1 = start_or_for->farg1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment then test
|
// increment then test
|
||||||
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL, MPFR_DEFAULT_RND);
|
mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr,
|
||||||
|
step->_value.mpfr, MPFR_DEFAULT_RND);
|
||||||
|
|
||||||
// for command: increment symbol too
|
// for command: increment symbol too
|
||||||
if (start_or_for->arg1 != -1)
|
if (start_or_for->arg1 != -1) {
|
||||||
{
|
object* obj;
|
||||||
object* obj;
|
unsigned int size;
|
||||||
unsigned int size;
|
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
|
||||||
|
|
||||||
// increase symbol variable
|
// increase symbol variable
|
||||||
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
|
_local_heap.replace_value(string(var->_value), myobj.farg1,
|
||||||
|
myobj.farg1->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//test value
|
// test loop value is out of range
|
||||||
if (myobj.farg1->_value > start_or_for->farg2->_value)
|
if (myobj.farg1->_value > start_or_for->farg2->_value) {
|
||||||
{
|
// end of loop
|
||||||
// end of loop
|
myobj.arg_bool = false; // init again next time
|
||||||
myobj.arg_bool = false;// init again next time
|
_calc_stack.pop_back(2);
|
||||||
_calc_stack.pop_back(2);
|
ret = -1;
|
||||||
return -1;
|
} else {
|
||||||
}
|
// for command: next instruction will be after symbol variable
|
||||||
else
|
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
|
||||||
{
|
// start command: next instruction will be after start command
|
||||||
// for command: next instruction will be after symbol variable
|
else
|
||||||
if (start_or_for->arg1 != -1)
|
ret = myobj.arg1 + 1;
|
||||||
return start_or_for->arg1 + 1;
|
|
||||||
// start command: next instruction will be after start command
|
|
||||||
else
|
|
||||||
return myobj.arg1 + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpn_step(branch& myobj)
|
return ret;
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
|
||||||
|
|
||||||
number* step = (number*)_stack->pop_back();
|
|
||||||
|
|
||||||
// end of loop if step is negative or zero
|
|
||||||
if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0)
|
|
||||||
ret = -1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// arg1 = index of start or for command in program
|
|
||||||
// farg1 = current count
|
|
||||||
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
|
||||||
if (! myobj.arg_bool)
|
|
||||||
{
|
|
||||||
myobj.arg_bool = true;
|
|
||||||
myobj.farg1 = start_or_for->farg1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment then test
|
|
||||||
mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEFAULT_RND);
|
|
||||||
|
|
||||||
// for command: increment symbol too
|
|
||||||
if (start_or_for->arg1 != -1)
|
|
||||||
{
|
|
||||||
object* obj;
|
|
||||||
unsigned int size;
|
|
||||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
|
||||||
|
|
||||||
// increase symbol variable
|
|
||||||
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// test loop value is out of range
|
|
||||||
if (myobj.farg1->_value > start_or_for->farg2->_value)
|
|
||||||
{
|
|
||||||
// end of loop
|
|
||||||
myobj.arg_bool = false;// init again next time
|
|
||||||
_calc_stack.pop_back(2);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// for command: next instruction will be after symbol variable
|
|
||||||
if (start_or_for->arg1 != -1)
|
|
||||||
ret = start_or_for->arg1 + 1;
|
|
||||||
// start command: next instruction will be after start command
|
|
||||||
else
|
|
||||||
ret = myobj.arg1 + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,130 +1,146 @@
|
||||||
void rpn_re()
|
void rpn_re() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->re()->mpfr, floating_t::s_mpfr_rnd));
|
_stack->pop_back();
|
||||||
_calc_stack.pop_back();
|
|
||||||
|
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
CHECK_MPFR(mpfr_set(re->_value.mpfr,
|
||||||
|
((complex*)_calc_stack.get_obj(0))->re()->mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
_calc_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_im()
|
void rpn_im() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->im()->mpfr, floating_t::s_mpfr_rnd));
|
_stack->pop_back();
|
||||||
_calc_stack.pop_back();
|
|
||||||
|
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
CHECK_MPFR(mpfr_set(im->_value.mpfr,
|
||||||
|
((complex*)_calc_stack.get_obj(0))->im()->mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
_calc_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_arg()
|
void rpn_arg() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
// calc atan2(x/y)
|
// calc atan2(x/y)
|
||||||
complex* cplx = (complex*)_stack->pop_back();
|
complex* cplx = (complex*)_stack->pop_back();
|
||||||
number* num = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
number* num =
|
||||||
|
(number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
_calc_stack.pop_back();
|
_calc_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_conj()
|
void rpn_conj() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
complex* cplx = (complex*)_stack->back();
|
complex* cplx = (complex*)_stack->back();
|
||||||
CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(
|
||||||
|
mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_r2c()
|
void rpn_r2c() {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.get_obj(1))->_value.mpfr, floating_t::s_mpfr_rnd));
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd));
|
_stack->pop_back();
|
||||||
_calc_stack.pop_back(2);
|
_stack->pop_back();
|
||||||
|
|
||||||
|
complex* cplx =
|
||||||
|
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||||
|
CHECK_MPFR(mpfr_set(cplx->re()->mpfr,
|
||||||
|
((number*)_calc_stack.get_obj(1))->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_set(cplx->im()->mpfr,
|
||||||
|
((number*)_calc_stack.get_obj(0))->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
_calc_stack.pop_back(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_c2r()
|
void rpn_c2r() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
_stack->pop_back();
|
_stack->pop_back();
|
||||||
|
|
||||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set(re->_value.mpfr,
|
||||||
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, floating_t::s_mpfr_rnd));
|
((complex*)_calc_stack.back())->re()->mpfr,
|
||||||
_calc_stack.pop_back();
|
floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_set(im->_value.mpfr,
|
||||||
|
((complex*)_calc_stack.back())->im()->mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
_calc_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_r2p()
|
void rpn_r2p() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
rpn_arg();
|
rpn_arg();
|
||||||
|
|
||||||
complex* cplx = (complex*)_stack->get_obj(1);
|
complex* cplx = (complex*)_stack->get_obj(1);
|
||||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr,
|
||||||
_stack->pop_back();
|
floating_t::s_mpfr_rnd));
|
||||||
|
_stack->pop_back();
|
||||||
rpn_swap();
|
|
||||||
rpn_abs();
|
rpn_swap();
|
||||||
cplx = (complex*)_stack->get_obj(1);
|
rpn_abs();
|
||||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
|
cplx = (complex*)_stack->get_obj(1);
|
||||||
_stack->pop_back();
|
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd));
|
||||||
|
_stack->pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_p2r()
|
void rpn_p2r() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||||
|
|
||||||
// assert complex is polar
|
|
||||||
complex* rhotheta = (complex*)_calc_stack.get_obj(1);
|
|
||||||
number* tmp = (number*)_calc_stack.get_obj(0);
|
|
||||||
complex* result = (complex*)_stack->back();
|
|
||||||
|
|
||||||
//calc cos(theta)
|
// assert complex is polar
|
||||||
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
complex* rhotheta = (complex*)_calc_stack.get_obj(1);
|
||||||
CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
number* tmp = (number*)_calc_stack.get_obj(0);
|
||||||
|
complex* result = (complex*)_stack->back();
|
||||||
|
|
||||||
//calc rcos(theta)
|
// calc cos(theta)
|
||||||
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(
|
||||||
|
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(
|
||||||
|
mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
//calc sin(theta)
|
// calc rcos(theta)
|
||||||
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr,
|
||||||
CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
//calc rsin(theta)
|
// calc sin(theta)
|
||||||
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(
|
||||||
|
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(
|
||||||
|
mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
// calc rsin(theta)
|
||||||
|
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr,
|
||||||
|
tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,230 +1,209 @@
|
||||||
//
|
//
|
||||||
void rpn_nop()
|
void rpn_nop() {
|
||||||
{
|
// nop
|
||||||
// nop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_good_bye()
|
void rpn_good_bye() { ERR_CONTEXT(ret_good_bye); }
|
||||||
{
|
|
||||||
ERR_CONTEXT(ret_good_bye);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_help()
|
void rpn_help() {
|
||||||
{
|
// software name
|
||||||
// software name
|
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
|
||||||
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
|
|
||||||
|
|
||||||
// description
|
// description
|
||||||
printf("%s\n\n", description);
|
printf("%s\n\n", description);
|
||||||
|
|
||||||
// syntax
|
// syntax
|
||||||
printf("%s\n", syntax);
|
printf("%s\n", syntax);
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
while(s_keywords[i].type != cmd_max)
|
while (s_keywords[i].type != cmd_max) {
|
||||||
{
|
if (s_keywords[i].comment.size() != 0) {
|
||||||
if (s_keywords[i].comment.size() != 0)
|
// titles in bold
|
||||||
{
|
if (s_keywords[i].type == cmd_undef) printf(ATTR_BOLD);
|
||||||
// titles in bold
|
// show title or keyword + comment
|
||||||
if (s_keywords[i].type==cmd_undef)
|
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
|
||||||
printf(ATTR_BOLD);
|
if (s_keywords[i].type == cmd_undef) printf(ATTR_OFF);
|
||||||
// show title or keyword + comment
|
|
||||||
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
|
|
||||||
if (s_keywords[i].type==cmd_undef)
|
|
||||||
printf(ATTR_OFF);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
i++;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
// show mode
|
// show mode
|
||||||
printf("Current float mode is ");
|
printf("Current float mode is ");
|
||||||
switch(number::s_mode)
|
switch (number::s_mode) {
|
||||||
{
|
case number::std:
|
||||||
case number::std: printf("'std'"); break;
|
printf("'std'");
|
||||||
case number::fix: printf("'fix'"); break;
|
break;
|
||||||
case number::sci: printf("'sci'"); break;
|
case number::fix:
|
||||||
default: printf("unknown"); break;
|
printf("'fix'");
|
||||||
|
break;
|
||||||
|
case number::sci:
|
||||||
|
printf("'sci'");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(" with %d digits after the decimal point\n", number::s_decimal_digits);
|
||||||
|
|
||||||
|
// bits precision, decimal digits and rounding mode
|
||||||
|
printf("Current floating point precision is %d bits\n",
|
||||||
|
(int)floating_t::s_mpfr_prec);
|
||||||
|
printf("Current rounding mode is \"%s\"\n",
|
||||||
|
floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int base_digits_from_bit_precision(int base, int bit_precision) {
|
||||||
|
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string make_digit_format(int decimal_digits, const char* printf_format) {
|
||||||
|
stringstream ss;
|
||||||
|
ss << MPFR_FORMAT_BEG;
|
||||||
|
ss << number::s_decimal_digits;
|
||||||
|
ss << printf_format;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_decimal_digits(double precision) {
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
||||||
|
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
||||||
|
double prec_max = (double)MPFR_PREC_MAX;
|
||||||
|
double prec_min = 0.0;
|
||||||
|
|
||||||
|
if (precision < prec_min || precision > prec_max) ret = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_std() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
double digits = double(((number*)_stack->pop_back())->_value);
|
||||||
|
|
||||||
|
if (check_decimal_digits(digits)) {
|
||||||
|
// set mode, decimal digits and print format
|
||||||
|
number::s_mode = number::std;
|
||||||
|
number::s_decimal_digits = (int)digits;
|
||||||
|
number::s_mpfr_printf_format =
|
||||||
|
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_fix() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
double digits = double(((number*)_stack->pop_back())->_value);
|
||||||
|
|
||||||
|
if (check_decimal_digits(digits)) {
|
||||||
|
// set mode, decimal digits and print format
|
||||||
|
number::s_mode = number::fix;
|
||||||
|
number::s_decimal_digits = (int)digits;
|
||||||
|
number::s_mpfr_printf_format =
|
||||||
|
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_sci() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
double digits = double(((number*)_stack->pop_back())->_value);
|
||||||
|
|
||||||
|
if (check_decimal_digits(digits)) {
|
||||||
|
// set mode, decimal digits and print format
|
||||||
|
number::s_mode = number::sci;
|
||||||
|
number::s_decimal_digits = (int)digits;
|
||||||
|
number::s_mpfr_printf_format =
|
||||||
|
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_version() {
|
||||||
|
// allocate and set object
|
||||||
|
unsigned int naked_entry_len = strlen(version);
|
||||||
|
ostring* str = (ostring*)_stack->allocate_back(
|
||||||
|
sizeof(ostring) + naked_entry_len + 1, cmd_string);
|
||||||
|
str->set(version, naked_entry_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_uname() {
|
||||||
|
// allocate and set object
|
||||||
|
unsigned int naked_entry_len = strlen(uname);
|
||||||
|
ostring* str = (ostring*)_stack->allocate_back(
|
||||||
|
sizeof(ostring) + naked_entry_len + 1, cmd_string);
|
||||||
|
str->set(uname, naked_entry_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_history() {
|
||||||
|
// see command history on stdout
|
||||||
|
int index = 0;
|
||||||
|
char* line = linenoiseHistoryLine(index);
|
||||||
|
while (line != NULL) {
|
||||||
|
cout << line << endl;
|
||||||
|
free(line);
|
||||||
|
line = linenoiseHistoryLine(++index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_type() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
|
int type = _stack->pop_back()->_type;
|
||||||
|
if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef;
|
||||||
|
|
||||||
|
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
|
||||||
|
unsigned int size = sizeof(symbol) + string_size + 1;
|
||||||
|
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
|
||||||
|
typ->set(object::s_cmd_type_string[type], string_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_default() { program::apply_default(); }
|
||||||
|
|
||||||
|
void rpn_precision() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
// set precision
|
||||||
|
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
if (prec >= (unsigned long)MPFR_PREC_MIN &&
|
||||||
|
prec <= (unsigned long)MPFR_PREC_MAX) {
|
||||||
|
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
|
||||||
|
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
|
||||||
|
|
||||||
|
// modify digits seen by user if std mode
|
||||||
|
if (number::s_mode == number::std) {
|
||||||
|
// calc max nb of digits user can see with the current bit precision
|
||||||
|
number::s_decimal_digits =
|
||||||
|
base_digits_from_bit_precision(10, floating_t::s_mpfr_prec);
|
||||||
|
number::s_mpfr_printf_format =
|
||||||
|
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||||
}
|
}
|
||||||
printf(" with %d digits after the decimal point\n", number::s_decimal_digits);
|
} else
|
||||||
|
ERR_CONTEXT(ret_out_of_range);
|
||||||
// bits precision, decimal digits and rounding mode
|
|
||||||
printf("Current floating point precision is %d bits\n", (int)floating_t::s_mpfr_prec);
|
|
||||||
printf("Current rounding mode is \"%s\"\n", floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
|
|
||||||
printf("\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int base_digits_from_bit_precision(int base, int bit_precision)
|
void rpn_round() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
}
|
|
||||||
|
|
||||||
string make_digit_format(int decimal_digits, const char* printf_format)
|
ostring* str = (ostring*)_stack->pop_back();
|
||||||
{
|
bool done = false;
|
||||||
stringstream ss;
|
for (int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++) {
|
||||||
ss << MPFR_FORMAT_BEG;
|
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value) {
|
||||||
ss << number::s_decimal_digits;
|
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
|
||||||
ss << printf_format;
|
done = true;
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check_decimal_digits(double precision)
|
|
||||||
{
|
|
||||||
bool ret = true;
|
|
||||||
|
|
||||||
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
|
||||||
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
|
||||||
double prec_max = (double)MPFR_PREC_MAX;
|
|
||||||
double prec_min = 0.0;
|
|
||||||
|
|
||||||
if (precision < prec_min || precision > prec_max)
|
|
||||||
ret = false;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_std()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
double digits = double(((number*)_stack->pop_back())->_value);
|
|
||||||
|
|
||||||
if (check_decimal_digits(digits))
|
|
||||||
{
|
|
||||||
// set mode, decimal digits and print format
|
|
||||||
number::s_mode = number::std;
|
|
||||||
number::s_decimal_digits = (int)digits;
|
|
||||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
if (!done) ERR_CONTEXT(ret_out_of_range);
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_fix()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
double digits = double(((number*)_stack->pop_back())->_value);
|
|
||||||
|
|
||||||
if (check_decimal_digits(digits))
|
|
||||||
{
|
|
||||||
// set mode, decimal digits and print format
|
|
||||||
number::s_mode = number::fix;
|
|
||||||
number::s_decimal_digits = (int)digits;
|
|
||||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_sci()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
double digits = double(((number*)_stack->pop_back())->_value);
|
|
||||||
|
|
||||||
if (check_decimal_digits(digits))
|
|
||||||
{
|
|
||||||
// set mode, decimal digits and print format
|
|
||||||
number::s_mode = number::sci;
|
|
||||||
number::s_decimal_digits = (int)digits;
|
|
||||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_version()
|
|
||||||
{
|
|
||||||
// allocate and set object
|
|
||||||
unsigned int naked_entry_len = strlen(version);
|
|
||||||
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
|
|
||||||
str->set(version, naked_entry_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_uname()
|
|
||||||
{
|
|
||||||
// allocate and set object
|
|
||||||
unsigned int naked_entry_len = strlen(uname);
|
|
||||||
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
|
|
||||||
str->set(uname, naked_entry_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_history()
|
|
||||||
{
|
|
||||||
//see command history on stdout
|
|
||||||
int index = 0;
|
|
||||||
char* line = linenoiseHistoryLine(index);
|
|
||||||
while(line != NULL)
|
|
||||||
{
|
|
||||||
cout<<line<<endl;
|
|
||||||
free(line);
|
|
||||||
line = linenoiseHistoryLine(++index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_type()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
int type = _stack->pop_back()->_type;
|
|
||||||
if (type < 0 || type >= (int)cmd_max)
|
|
||||||
type = (int)cmd_undef;
|
|
||||||
|
|
||||||
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
|
|
||||||
unsigned int size = sizeof(symbol)+string_size+1;
|
|
||||||
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
|
|
||||||
typ->set(object::s_cmd_type_string[type], string_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_default()
|
|
||||||
{
|
|
||||||
program::apply_default();
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_precision()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
//set precision
|
|
||||||
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
|
||||||
if (prec>=(unsigned long)MPFR_PREC_MIN && prec<=(unsigned long)MPFR_PREC_MAX)
|
|
||||||
{
|
|
||||||
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
|
|
||||||
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
|
|
||||||
|
|
||||||
// modify digits seen by user if std mode
|
|
||||||
if (number::s_mode == number::std)
|
|
||||||
{
|
|
||||||
// calc max nb of digits user can see with the current bit precision
|
|
||||||
number::s_decimal_digits = base_digits_from_bit_precision(10, floating_t::s_mpfr_prec);
|
|
||||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_round()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
||||||
|
|
||||||
ostring* str = (ostring*)_stack->pop_back();
|
|
||||||
bool done = false;
|
|
||||||
for(int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++)
|
|
||||||
{
|
|
||||||
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value)
|
|
||||||
{
|
|
||||||
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!done)
|
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
|
||||||
}
|
}
|
||||||
|
|
570
src/rpn-logs.hpp
570
src/rpn-logs.hpp
|
@ -1,377 +1,337 @@
|
||||||
void rpn_e(void)
|
void rpn_e(void) {
|
||||||
{
|
number* euler =
|
||||||
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
euler->_value = 1L;
|
euler->_value = 1L;
|
||||||
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(
|
||||||
|
mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_log10()
|
void rpn_log10() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
// log10(z)=ln(z)/ln(10)
|
||||||
//log10(z)=ln(z)/ln(10)
|
rpn_ln();
|
||||||
rpn_ln();
|
|
||||||
|
|
||||||
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
number* ten =
|
||||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_ln();
|
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_div();
|
rpn_ln();
|
||||||
}
|
rpn_div();
|
||||||
else
|
} else
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_alog10()
|
void rpn_alog10() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
number* ten =
|
||||||
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_ln();
|
rpn_ln();
|
||||||
rpn_mul();
|
rpn_mul();
|
||||||
rpn_exp();
|
rpn_exp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_log2()
|
void rpn_log2() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
// log2(z)=ln(z)/ln(2)
|
||||||
//log2(z)=ln(z)/ln(2)
|
rpn_ln();
|
||||||
rpn_ln();
|
|
||||||
|
|
||||||
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
number* two =
|
||||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_ln();
|
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_div();
|
rpn_ln();
|
||||||
}
|
rpn_div();
|
||||||
else
|
} else
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_alog2()
|
void rpn_alog2() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
number* two =
|
||||||
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_ln();
|
rpn_ln();
|
||||||
rpn_mul();
|
rpn_mul();
|
||||||
rpn_exp();
|
rpn_exp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_ln()
|
void rpn_ln() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
number* left = (number*)_stack->back();
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
// x<0 -> ln(x) = ln(-x)+i*pi
|
// x<0 -> ln(x) = ln(-x)+i*pi
|
||||||
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0)
|
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) {
|
||||||
{
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
_stack->pop_back();
|
||||||
_stack->pop_back();
|
left = (number*)_calc_stack.back();
|
||||||
left = (number*)_calc_stack.back();
|
|
||||||
|
|
||||||
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
complex* cplx =
|
||||||
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
|
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||||
CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr,
|
||||||
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
floating_t::s_mpfr_rnd));
|
||||||
_calc_stack.pop_back();
|
CHECK_MPFR(
|
||||||
}
|
mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||||
else
|
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
|
_calc_stack.pop_back();
|
||||||
}
|
} else
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr,
|
||||||
{
|
floating_t::s_mpfr_rnd));
|
||||||
// ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y)
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
// ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y)
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
|
|
||||||
// 1. atan(x/y)
|
// 1. atan(x/y)
|
||||||
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
// 2. 0.5*ln(x*x+y*y)
|
// 2. 0.5*ln(x*x+y*y)
|
||||||
CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
_calc_stack.pop_back();
|
_calc_stack.pop_back();
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_exp()
|
void rpn_exp() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// exp(x)*(cos(y)+i sin(y))
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
{
|
|
||||||
// exp(x)*(cos(y)+i sin(y))
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
_calc_stack.pop_back();
|
_calc_stack.pop_back();
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_expm()
|
void rpn_expm() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
// exp(x)-1
|
||||||
//exp(x)-1
|
rpn_exp();
|
||||||
rpn_exp();
|
|
||||||
|
|
||||||
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
number* one =
|
||||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_minus();
|
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
}
|
rpn_minus();
|
||||||
else
|
} else
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_lnp1()
|
void rpn_lnp1() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||||
{
|
// ln(x+1)
|
||||||
//ln(x+1)
|
number* one =
|
||||||
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_plus();
|
rpn_plus();
|
||||||
|
|
||||||
rpn_ln();
|
rpn_ln();
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_sinh()
|
void rpn_sinh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
{
|
|
||||||
// sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
floating_t* tmp =
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
->_value;
|
||||||
|
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||||
|
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
_calc_stack.pop_back(2);
|
_calc_stack.pop_back(2);
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_asinh()
|
void rpn_asinh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// asinh(z)=ln(z+sqrt(1+z*z))
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
rpn_dup();
|
||||||
{
|
rpn_square();
|
||||||
// asinh(z)=ln(z+sqrt(1+z*z))
|
number* num =
|
||||||
rpn_dup();
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_square();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_plus();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
rpn_squareroot();
|
||||||
rpn_plus();
|
rpn_plus();
|
||||||
rpn_squareroot();
|
rpn_ln();
|
||||||
rpn_plus();
|
} else
|
||||||
rpn_ln();
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_cosh()
|
void rpn_cosh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
{
|
|
||||||
// acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
floating_t* tmp =
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
->_value;
|
||||||
|
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||||
|
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
_calc_stack.pop_back(2);
|
_calc_stack.pop_back(2);
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_acosh()
|
void rpn_acosh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// acosh(z)=ln(z+sqrt(z+1)sqrt(z-1))
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
rpn_dup();
|
||||||
{
|
number* num =
|
||||||
// acosh(z)=ln(z+sqrt(z+1)sqrt(z-1))
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_dup();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_plus();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
rpn_dup();
|
||||||
rpn_plus();
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_dup();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_minus();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
rpn_mul();
|
||||||
rpn_minus();
|
rpn_squareroot();
|
||||||
rpn_mul();
|
rpn_plus();
|
||||||
rpn_squareroot();
|
rpn_ln();
|
||||||
rpn_plus();
|
} else
|
||||||
rpn_ln();
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_tanh()
|
void rpn_tanh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
rpn_dup();
|
||||||
{
|
|
||||||
// tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
|
|
||||||
rpn_dup();
|
|
||||||
|
|
||||||
floating_t* x = ((complex*)_stack->get_obj(1))->re();
|
floating_t* x = ((complex*)_stack->get_obj(1))->re();
|
||||||
floating_t* y = ((complex*)_stack->get_obj(1))->im();
|
floating_t* y = ((complex*)_stack->get_obj(1))->im();
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(1))->re();
|
floating_t* re = ((complex*)_stack->get_obj(1))->re();
|
||||||
floating_t* im = ((complex*)_stack->get_obj(1))->im();
|
floating_t* im = ((complex*)_stack->get_obj(1))->im();
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_div();
|
rpn_div();
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_atanh()
|
void rpn_atanh() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// atanh(z)=0.5*ln((1+z)/(1-z))
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
rpn_dup();
|
||||||
{
|
number* num =
|
||||||
// atanh(z)=0.5*ln((1+z)/(1-z))
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_dup();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_plus();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
rpn_swap();
|
||||||
rpn_plus();
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_swap();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_minus();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
rpn_neg();
|
||||||
rpn_minus();
|
rpn_div();
|
||||||
rpn_neg();
|
rpn_ln();
|
||||||
rpn_div();
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
rpn_ln();
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
rpn_mul();
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
|
} else
|
||||||
rpn_mul();
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,167 +1,139 @@
|
||||||
//
|
//
|
||||||
bool find_variable(string& variable, object*& obj, unsigned int& size)
|
bool find_variable(string& variable, object*& obj, unsigned int& size) {
|
||||||
{
|
bool found = false;
|
||||||
bool found = false;
|
program* parent = _parent_prog;
|
||||||
program* parent = _parent_prog;
|
|
||||||
|
|
||||||
// find variable in local heap, parens heaps, global heap
|
// find variable in local heap, parens heaps, global heap
|
||||||
if (_local_heap.get(variable, obj, size))
|
if (_local_heap.get(variable, obj, size))
|
||||||
|
found = true;
|
||||||
|
else {
|
||||||
|
while (parent != NULL) {
|
||||||
|
if (parent->_local_heap.get(variable, obj, size)) {
|
||||||
found = true;
|
found = true;
|
||||||
else
|
break;
|
||||||
{
|
}
|
||||||
while(parent != NULL)
|
parent = parent->_parent_prog;
|
||||||
{
|
|
||||||
if (parent->_local_heap.get(variable, obj, size))
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parent = parent->_parent_prog;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
if (_heap->get(variable, obj, size))
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!found) {
|
||||||
return found;
|
if (_heap->get(variable, obj, size)) found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_eval(void)
|
void rpn_eval(void) {
|
||||||
{
|
bool run_prog = false;
|
||||||
bool run_prog = false;
|
string prog_text;
|
||||||
string prog_text;
|
|
||||||
|
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (IS_ARG_TYPE(0, cmd_symbol))
|
if (IS_ARG_TYPE(0, cmd_symbol)) {
|
||||||
{
|
// recall a variable
|
||||||
// recall a variable
|
object* obj;
|
||||||
object* obj;
|
unsigned int size;
|
||||||
unsigned int size;
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
|
// if variable holds a program, run this program
|
||||||
// if variable holds a program, run this program
|
if (find_variable(variable, obj, size)) {
|
||||||
if (find_variable(variable, obj, size))
|
if (obj->_type == cmd_program) {
|
||||||
{
|
prog_text = ((oprogram*)obj)->_value;
|
||||||
if (obj->_type == cmd_program)
|
(void)_stack->pop_back();
|
||||||
{
|
|
||||||
prog_text = ((oprogram*)obj)->_value;
|
|
||||||
(void)_stack->pop_back();
|
|
||||||
run_prog = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// else recall this variable (i.e. stack its content)
|
|
||||||
(void)_stack->pop_back();
|
|
||||||
stack::copy_and_push_back(obj, *_stack, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_unknown_variable);
|
|
||||||
}
|
|
||||||
else if (IS_ARG_TYPE(0, cmd_program))
|
|
||||||
{
|
|
||||||
// eval a program
|
|
||||||
prog_text = ((oprogram*)_stack->pop_back())->_value;
|
|
||||||
run_prog = true;
|
run_prog = true;
|
||||||
}
|
} else {
|
||||||
else
|
// else recall this variable (i.e. stack its content)
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
(void)_stack->pop_back();
|
||||||
|
stack::copy_and_push_back(obj, *_stack, size);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_unknown_variable);
|
||||||
|
} else if (IS_ARG_TYPE(0, cmd_program)) {
|
||||||
|
// eval a program
|
||||||
|
prog_text = ((oprogram*)_stack->pop_back())->_value;
|
||||||
|
run_prog = true;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
|
||||||
// run prog if any
|
// run prog if any
|
||||||
if (run_prog)
|
if (run_prog) {
|
||||||
{
|
program prog(this);
|
||||||
program prog(this);
|
|
||||||
|
|
||||||
// make program from entry
|
// make program from entry
|
||||||
if (program::parse(prog_text.c_str(), prog) == ret_ok)
|
if (program::parse(prog_text.c_str(), prog) == ret_ok) {
|
||||||
{
|
// run it
|
||||||
// run it
|
prog.run(*_stack, *_heap);
|
||||||
prog.run(*_stack, *_heap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// carefull, this not a command but a branch
|
// carefull, this not a command but a branch
|
||||||
int rpn_inprog(branch& myobj)
|
int rpn_inprog(branch& myobj) {
|
||||||
{
|
string context("->"); // for showing errors
|
||||||
string context("->");// for showing errors
|
int count_symbols = 0;
|
||||||
int count_symbols = 0;
|
bool prog_found = false;
|
||||||
bool prog_found = false;
|
|
||||||
|
|
||||||
if (myobj.arg1 == -1)
|
if (myobj.arg1 == -1) {
|
||||||
{
|
ERR_CONTEXT(ret_unknown_err);
|
||||||
ERR_CONTEXT(ret_unknown_err);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
|
// syntax must be
|
||||||
|
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
|
||||||
|
|
||||||
|
// find next oprogram object
|
||||||
|
for (unsigned int i = myobj.arg1 + 1; i < size(); i++) {
|
||||||
|
// count symbol
|
||||||
|
if (seq_type(i) == cmd_symbol) count_symbols++;
|
||||||
|
// stop if prog
|
||||||
|
else if (seq_type(i) == cmd_program) {
|
||||||
|
prog_found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
// found something other than symbol
|
||||||
// syntax must be
|
else {
|
||||||
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
show_error(_err, context);
|
||||||
// find next oprogram object
|
return -1;
|
||||||
for (unsigned int i = myobj.arg1 + 1; i < size(); i++)
|
|
||||||
{
|
|
||||||
// count symbol
|
|
||||||
if (seq_type(i) == cmd_symbol)
|
|
||||||
count_symbols++;
|
|
||||||
// stop if prog
|
|
||||||
else if (seq_type(i) == cmd_program)
|
|
||||||
{
|
|
||||||
prog_found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// found something other than symbol
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
show_error(_err, context);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// found 0 symbols
|
// found 0 symbols
|
||||||
if (count_symbols == 0)
|
if (count_symbols == 0) {
|
||||||
{
|
ERR_CONTEXT(ret_syntax);
|
||||||
ERR_CONTEXT(ret_syntax);
|
show_error(_err, context);
|
||||||
show_error(_err, context);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// <oprogram> is missing
|
// <oprogram> is missing
|
||||||
if (! prog_found)
|
if (!prog_found) {
|
||||||
{
|
ERR_CONTEXT(ret_syntax);
|
||||||
ERR_CONTEXT(ret_syntax);
|
show_error(_err, context);
|
||||||
show_error(_err, context);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// check symbols number vs stack size
|
// check symbols number vs stack size
|
||||||
if (stack_size() < count_symbols)
|
if (stack_size() < count_symbols) {
|
||||||
{
|
ERR_CONTEXT(ret_missing_operand);
|
||||||
ERR_CONTEXT(ret_missing_operand);
|
show_error(_err, context);
|
||||||
show_error(_err, context);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// load variables
|
// load variables
|
||||||
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--)
|
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) {
|
||||||
{
|
_local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0),
|
||||||
_local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0));
|
_stack->get_len(0));
|
||||||
(void)_stack->pop_back();
|
(void)_stack->pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the program
|
// run the program
|
||||||
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
||||||
program prog(this);
|
program prog(this);
|
||||||
|
|
||||||
// make the program from entry
|
// make the program from entry
|
||||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
if (program::parse(entry.c_str(), prog) == ret_ok) {
|
||||||
{
|
// run it
|
||||||
// run it
|
prog.run(*_stack, *_heap);
|
||||||
prog.run(*_stack, *_heap);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// point on next command
|
// point on next command
|
||||||
return myobj.arg1 + count_symbols + 2;
|
return myobj.arg1 + count_symbols + 2;
|
||||||
}
|
}
|
||||||
|
|
1231
src/rpn-real.hpp
1231
src/rpn-real.hpp
File diff suppressed because it is too large
Load diff
|
@ -1,155 +1,140 @@
|
||||||
//
|
//
|
||||||
void rpn_swap(void)
|
void rpn_swap(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
(void)_stack->pop_back(2);
|
||||||
(void)_stack->pop_back(2);
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
_calc_stack.pop_back(2);
|
||||||
_calc_stack.pop_back(2);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
void rpn_drop(void)
|
void rpn_drop(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
(void)_stack->pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_drop2(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
(void)_stack->pop_back(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_dropn(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
MIN_ARGUMENTS(args + 1);
|
||||||
|
|
||||||
|
(void)_stack->pop_back(args + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_erase(void) { (void)_stack->pop_back(_stack->size()); }
|
||||||
|
|
||||||
|
void rpn_dup(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_dup2(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_dupn(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
MIN_ARGUMENTS(args + 1);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
for (int i = 0; i < args; i++)
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_pick(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
unsigned int to_pick =
|
||||||
|
(unsigned int)int(((number*)_stack->pop_back())->_value);
|
||||||
|
|
||||||
|
// treat stack depth errors
|
||||||
|
if ((to_pick == 0) || (to_pick > _stack->size())) {
|
||||||
|
ERR_CONTEXT(ret_out_of_range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_rot(void) {
|
||||||
|
MIN_ARGUMENTS(3);
|
||||||
|
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack);
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
(void)_stack->pop_back(3);
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack);
|
||||||
|
_calc_stack.pop_back(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_depth(void) {
|
||||||
|
unsigned long depth = (unsigned long)_stack->size();
|
||||||
|
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
num->set(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_roll(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
MIN_ARGUMENTS(args + 1);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
for (int i = 0; i < args; i++) {
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
(void)_stack->pop_back();
|
(void)_stack->pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < args; i++)
|
||||||
|
stack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack);
|
||||||
|
stack::copy_and_push_back(_calc_stack, args - 1, *_stack);
|
||||||
|
|
||||||
|
_calc_stack.pop_back(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_drop2(void)
|
void rpn_rolld(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
(void)_stack->pop_back(2);
|
|
||||||
|
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||||
|
floating_t::s_mpfr_rnd);
|
||||||
|
MIN_ARGUMENTS(args + 1);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
for (int i = 0; i < args; i++) {
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
(void)_stack->pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack);
|
||||||
|
|
||||||
|
for (int i = 1; i < args; i++)
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack);
|
||||||
|
|
||||||
|
_calc_stack.pop_back(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_dropn(void)
|
void rpn_over(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||||
MIN_ARGUMENTS(args+1);
|
|
||||||
|
|
||||||
(void)_stack->pop_back(args+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_erase(void)
|
|
||||||
{
|
|
||||||
(void)_stack->pop_back(_stack->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_dup(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, *_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_dup2(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_dupn(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
|
||||||
MIN_ARGUMENTS(args+1);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
for (int i=0;i<args;i++)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-args, *_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_pick(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_back())->_value);
|
|
||||||
|
|
||||||
// treat stack depth errors
|
|
||||||
if ((to_pick == 0) || (to_pick > _stack->size()))
|
|
||||||
{
|
|
||||||
ERR_CONTEXT(ret_out_of_range);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-to_pick, *_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_rot(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(3);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-3, _calc_stack);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
(void)_stack->pop_back(3);
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-3, *_stack);
|
|
||||||
_calc_stack.pop_back(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_depth(void)
|
|
||||||
{
|
|
||||||
unsigned long depth = (unsigned long)_stack->size();
|
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
num->set(depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_roll(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
|
||||||
MIN_ARGUMENTS(args+1);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
for(int i=0;i<args;i++)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
(void)_stack->pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=1;i<args;i++)
|
|
||||||
stack::copy_and_push_back(_calc_stack, args-1-i, *_stack);
|
|
||||||
stack::copy_and_push_back(_calc_stack, args-1, *_stack);
|
|
||||||
|
|
||||||
_calc_stack.pop_back(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_rolld(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
|
||||||
MIN_ARGUMENTS(args+1);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
for(int i=0;i<args;i++)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
(void)_stack->pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-args, *_stack);
|
|
||||||
|
|
||||||
for(int i=1;i<args;i++)
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-i, *_stack);
|
|
||||||
|
|
||||||
_calc_stack.pop_back(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_over(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,327 +1,273 @@
|
||||||
//
|
//
|
||||||
void rpn_sto(void)
|
void rpn_sto(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
|
||||||
|
|
||||||
string name(((symbol*)_stack->pop_back())->_value);
|
string name(((symbol*)_stack->pop_back())->_value);
|
||||||
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
|
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
|
||||||
(void)_stack->pop_back();
|
(void)_stack->pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void rpn_stoadd(void)
|
void rpn_stoadd(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||||
{
|
// get variable value on stack level 1, make op then modify variable
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_plus();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
|
||||||
{
|
|
||||||
// copy value, get variable value on stack level 1,
|
|
||||||
// put back value on stack level 1, make op then modify variable
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
rpn_plus();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_stosub(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_minus();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
|
||||||
{
|
|
||||||
// copy value, get variable value on stack level 1,
|
|
||||||
// put back value on stack level 1, make op then modify variable
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
rpn_minus();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_stomul(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_mul();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
|
||||||
{
|
|
||||||
// copy value, get variable value on stack level 1,
|
|
||||||
// put back value on stack level 1, make op then modify variable
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
rpn_mul();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_stodiv(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_div();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
|
||||||
{
|
|
||||||
// copy value, get variable value on stack level 1,
|
|
||||||
// put back value on stack level 1, make op then modify variable
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
_stack->pop_back();
|
|
||||||
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
rpn_div();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_stoneg(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol)
|
|
||||||
{
|
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_neg();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_stoinv(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_symbol)
|
|
||||||
{
|
|
||||||
// get variable value on stack level 1, make op then modify variable
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
|
||||||
rpn_rcl();
|
|
||||||
if (_err == ret_ok)
|
|
||||||
{
|
|
||||||
rpn_inv();
|
|
||||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
|
||||||
_stack->pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_rcl(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
|
||||||
|
|
||||||
// recall a variable
|
|
||||||
object* obj;
|
|
||||||
unsigned int size;
|
|
||||||
string variable(((symbol*)_stack->back())->_value);
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
// mind the order of heaps
|
if (_err == ret_ok) {
|
||||||
if (find_variable(variable, obj, size))
|
rpn_plus();
|
||||||
{
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
(void)_stack->pop_back();
|
_stack->pop_back();
|
||||||
stack::copy_and_push_back(obj, *_stack, size);
|
|
||||||
}
|
}
|
||||||
else
|
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||||
ERR_CONTEXT(ret_unknown_variable);
|
_stack->get_type(0) == cmd_number) {
|
||||||
|
// copy value, get variable value on stack level 1,
|
||||||
|
// put back value on stack level 1, make op then modify variable
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
|
rpn_plus();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_edit(void)
|
void rpn_stosub(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
FILE* tmp = tmpfile();
|
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||||
if (tmp != NULL)
|
// get variable value on stack level 1, make op then modify variable
|
||||||
{
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
// re-write stack objet in a stream
|
rpn_rcl();
|
||||||
((object*)_stack->pop_back())->show(tmp);
|
if (_err == ret_ok) {
|
||||||
|
rpn_minus();
|
||||||
// edit: stuff chars using readline facility
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
int len = (int)ftell(tmp);
|
_stack->pop_back();
|
||||||
rewind(tmp);
|
|
||||||
|
|
||||||
// get stream data
|
|
||||||
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
|
|
||||||
if (file_data != MAP_FAILED)
|
|
||||||
{
|
|
||||||
// set it as the linenoise line entry
|
|
||||||
linenoisePreloadBuffer((const char*)file_data);
|
|
||||||
munmap(file_data, len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_runtime_error);
|
|
||||||
|
|
||||||
fclose(tmp);
|
|
||||||
}
|
}
|
||||||
else
|
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||||
ERR_CONTEXT(ret_runtime_error);
|
_stack->get_type(0) == cmd_number) {
|
||||||
|
// copy value, get variable value on stack level 1,
|
||||||
|
// put back value on stack level 1, make op then modify variable
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
|
rpn_minus();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_stomul(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
|
||||||
|
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||||
|
// get variable value on stack level 1, make op then modify variable
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
rpn_mul();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||||
|
_stack->get_type(0) == cmd_number) {
|
||||||
|
// copy value, get variable value on stack level 1,
|
||||||
|
// put back value on stack level 1, make op then modify variable
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
|
rpn_mul();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_stodiv(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
|
||||||
|
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||||
|
// get variable value on stack level 1, make op then modify variable
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
rpn_div();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||||
|
_stack->get_type(0) == cmd_number) {
|
||||||
|
// copy value, get variable value on stack level 1,
|
||||||
|
// put back value on stack level 1, make op then modify variable
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
_stack->pop_back();
|
||||||
|
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
|
rpn_div();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_stoneg(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
|
if (_stack->get_type(0) == cmd_symbol) {
|
||||||
|
// get variable value on stack level 1, make op then modify variable
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
rpn_neg();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_stoinv(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
|
if (_stack->get_type(0) == cmd_symbol) {
|
||||||
|
// get variable value on stack level 1, make op then modify variable
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
rpn_rcl();
|
||||||
|
if (_err == ret_ok) {
|
||||||
|
rpn_inv();
|
||||||
|
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||||
|
_stack->pop_back();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_rcl(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||||
|
|
||||||
|
// recall a variable
|
||||||
|
object* obj;
|
||||||
|
unsigned int size;
|
||||||
|
string variable(((symbol*)_stack->back())->_value);
|
||||||
|
|
||||||
|
// mind the order of heaps
|
||||||
|
if (find_variable(variable, obj, size)) {
|
||||||
|
(void)_stack->pop_back();
|
||||||
|
stack::copy_and_push_back(obj, *_stack, size);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_unknown_variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_edit(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
|
FILE* tmp = tmpfile();
|
||||||
|
if (tmp != NULL) {
|
||||||
|
// re-write stack objet in a stream
|
||||||
|
((object*)_stack->pop_back())->show(tmp);
|
||||||
|
|
||||||
|
// edit: stuff chars using readline facility
|
||||||
|
int len = (int)ftell(tmp);
|
||||||
|
rewind(tmp);
|
||||||
|
|
||||||
|
// get stream data
|
||||||
|
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
|
||||||
|
if (file_data != MAP_FAILED) {
|
||||||
|
// set it as the linenoise line entry
|
||||||
|
linenoisePreloadBuffer((const char*)file_data);
|
||||||
|
munmap(file_data, len);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_runtime_error);
|
||||||
|
|
||||||
|
fclose(tmp);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_runtime_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// carefull : this is not a langage command
|
// carefull : this is not a langage command
|
||||||
void auto_rcl(symbol* symb)
|
void auto_rcl(symbol* symb) {
|
||||||
{
|
if (symb->_auto_eval) {
|
||||||
if (symb->_auto_eval)
|
|
||||||
{
|
|
||||||
object* obj;
|
|
||||||
unsigned int size;
|
|
||||||
string variable(symb->_value);
|
|
||||||
|
|
||||||
// mind the order of heaps
|
|
||||||
if (find_variable(variable, obj, size))
|
|
||||||
{
|
|
||||||
stack::copy_and_push_back(obj, *_stack, size);
|
|
||||||
if (obj->_type == cmd_program)
|
|
||||||
rpn_eval();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_purge(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
|
||||||
|
|
||||||
string name(((symbol*)_stack->pop_back())->_value);
|
|
||||||
if (!_heap->erase(name))
|
|
||||||
ERR_CONTEXT(ret_unknown_variable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_vars(void)
|
|
||||||
{
|
|
||||||
object* obj;
|
object* obj;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
program* parent = _parent_prog;
|
string variable(symb->_value);
|
||||||
string name;
|
|
||||||
|
|
||||||
// heap variables
|
// mind the order of heaps
|
||||||
for (int i=0; i<(int)_heap->count_vars(); i++)
|
if (find_variable(variable, obj, size)) {
|
||||||
{
|
stack::copy_and_push_back(obj, *_stack, size);
|
||||||
(void)_heap->get_by_index(i, name, obj, size);
|
if (obj->_type == cmd_program) rpn_eval();
|
||||||
printf("var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
} else
|
||||||
obj->show();
|
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||||
printf("\n");
|
} else
|
||||||
}
|
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||||
|
|
||||||
// parents local variables
|
|
||||||
while (parent != NULL)
|
|
||||||
{
|
|
||||||
for (int i=0; i<(int)parent->_local_heap.size(); i++)
|
|
||||||
{
|
|
||||||
(void)parent->_local_heap.get_by_index(i, name, obj, size);
|
|
||||||
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
|
||||||
obj->show();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
parent = parent->_parent_prog;
|
|
||||||
}
|
|
||||||
|
|
||||||
// local variables
|
|
||||||
for (int i=0; i<(int)_local_heap.size(); i++)
|
|
||||||
{
|
|
||||||
(void)_local_heap.get_by_index(i, name, obj, size);
|
|
||||||
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
|
||||||
obj->show();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_clusr(void)
|
void rpn_purge(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
_heap->erase_all();
|
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||||
|
|
||||||
|
string name(((symbol*)_stack->pop_back())->_value);
|
||||||
|
if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rpn_vars(void) {
|
||||||
|
object* obj;
|
||||||
|
unsigned int size;
|
||||||
|
program* parent = _parent_prog;
|
||||||
|
string name;
|
||||||
|
|
||||||
|
// heap variables
|
||||||
|
for (int i = 0; i < (int)_heap->count_vars(); i++) {
|
||||||
|
(void)_heap->get_by_index(i, name, obj, size);
|
||||||
|
printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||||
|
object::s_cmd_type_string[obj->_type]);
|
||||||
|
obj->show();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parents local variables
|
||||||
|
while (parent != NULL) {
|
||||||
|
for (int i = 0; i < (int)parent->_local_heap.size(); i++) {
|
||||||
|
(void)parent->_local_heap.get_by_index(i, name, obj, size);
|
||||||
|
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||||
|
object::s_cmd_type_string[obj->_type]);
|
||||||
|
obj->show();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
parent = parent->_parent_prog;
|
||||||
|
}
|
||||||
|
|
||||||
|
// local variables
|
||||||
|
for (int i = 0; i < (int)_local_heap.size(); i++) {
|
||||||
|
(void)_local_heap.get_by_index(i, name, obj, size);
|
||||||
|
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||||
|
object::s_cmd_type_string[obj->_type]);
|
||||||
|
obj->show();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_clusr(void) { _heap->erase_all(); }
|
||||||
|
|
|
@ -1,152 +1,140 @@
|
||||||
void rpn_instr()
|
void rpn_instr() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
// stringify only if not already a string
|
// stringify only if not already a string
|
||||||
if (_stack->get_type(0) != cmd_string)
|
if (_stack->get_type(0) != cmd_string) {
|
||||||
{
|
// write the object in stack(0) in a string and remove this obj
|
||||||
// write the object in stack(0) in a string and remove this obj
|
FILE* tmp = tmpfile();
|
||||||
FILE* tmp = tmpfile();
|
if (tmp != NULL) {
|
||||||
if (tmp != NULL)
|
((object*)_stack->pop_back())->show(tmp);
|
||||||
{
|
|
||||||
((object*)_stack->pop_back())->show(tmp);
|
|
||||||
|
|
||||||
// reserve the correct size on stack
|
// reserve the correct size on stack
|
||||||
unsigned int str_size = (unsigned int)ftell(tmp);
|
unsigned int str_size = (unsigned int)ftell(tmp);
|
||||||
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
ostring* str = (ostring*)_stack->allocate_back(
|
||||||
str->_len = str_size;
|
str_size + 1 + sizeof(ostring), cmd_string);
|
||||||
|
str->_len = str_size;
|
||||||
|
|
||||||
// fill the obj
|
// fill the obj
|
||||||
rewind(tmp);
|
rewind(tmp);
|
||||||
if (fread(str->_value, str_size, 1, tmp) != 1)
|
if (fread(str->_value, str_size, 1, tmp) != 1)
|
||||||
ERR_CONTEXT(ret_runtime_error);
|
ERR_CONTEXT(ret_runtime_error);
|
||||||
str->_value[str_size] = 0;
|
str->_value[str_size] = 0;
|
||||||
fclose(tmp);
|
fclose(tmp);
|
||||||
}
|
} else
|
||||||
else
|
ERR_CONTEXT(ret_runtime_error);
|
||||||
ERR_CONTEXT(ret_runtime_error);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_strout()
|
void rpn_strout() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
||||||
|
|
||||||
string entry(((ostring*)_stack->pop_back())->_value);
|
string entry(((ostring*)_stack->pop_back())->_value);
|
||||||
|
|
||||||
program prog;
|
program prog;
|
||||||
|
|
||||||
// make program from string in stack level 1
|
// make program from string in stack level 1
|
||||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||||
// run it
|
// run it
|
||||||
prog.run(*_stack, *_heap);
|
prog.run(*_stack, *_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_chr()
|
void rpn_chr() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
// get arg as number % 256
|
// get arg as number % 256
|
||||||
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr,
|
||||||
if (the_chr<32 || the_chr>126)
|
floating_t::s_mpfr_rnd);
|
||||||
the_chr = '.';
|
if (the_chr < 32 || the_chr > 126) the_chr = '.';
|
||||||
|
|
||||||
// reserve the correct size on stack (1 char)
|
// reserve the correct size on stack (1 char)
|
||||||
unsigned int str_size = 1;
|
unsigned int str_size = 1;
|
||||||
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
ostring* str = (ostring*)_stack->allocate_back(str_size + 1 + sizeof(ostring),
|
||||||
|
cmd_string);
|
||||||
|
str->_len = str_size;
|
||||||
|
str->_value[0] = the_chr;
|
||||||
|
str->_value[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_num() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
|
|
||||||
|
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0];
|
||||||
|
number* numb =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
numb->_value = the_chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_strsize() {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
|
|
||||||
|
double len = ((ostring*)_stack->pop_back())->_len;
|
||||||
|
number* numb =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
numb->_value = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_strpos() {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||||
|
|
||||||
|
long pos = 0;
|
||||||
|
char* src = ((ostring*)_stack->get_obj(1))->_value;
|
||||||
|
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
|
||||||
|
if (found != NULL) pos = (long)(found - src) + 1L;
|
||||||
|
|
||||||
|
_stack->pop_back(2);
|
||||||
|
|
||||||
|
number* numb =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
numb->_value = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_strsub() {
|
||||||
|
MIN_ARGUMENTS(3);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
|
ARG_MUST_BE_OF_TYPE(2, cmd_string);
|
||||||
|
|
||||||
|
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
|
||||||
|
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
|
||||||
|
long len = ((ostring*)_stack->get_obj(2))->_len;
|
||||||
|
bool result_is_void = false;
|
||||||
|
|
||||||
|
_stack->pop_back(2);
|
||||||
|
|
||||||
|
if (first < 0) first = 0;
|
||||||
|
if (last < 0) last = 0;
|
||||||
|
if (first > len && last > len)
|
||||||
|
result_is_void = true;
|
||||||
|
else {
|
||||||
|
if (first > len) first = len - 1;
|
||||||
|
if (last > len) last = len - 1;
|
||||||
|
if (first > last) result_is_void = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result_is_void) {
|
||||||
|
unsigned int str_size = last - first + 1;
|
||||||
|
ostring* str = (ostring*)_calc_stack.allocate_back(
|
||||||
|
str_size + 1 + sizeof(ostring), cmd_string);
|
||||||
str->_len = str_size;
|
str->_len = str_size;
|
||||||
str->_value[0] = the_chr;
|
|
||||||
str->_value[1] = 0;
|
memcpy(((ostring*)_calc_stack.back())->_value,
|
||||||
}
|
((ostring*)_stack->get_obj(0))->_value + first, str_size);
|
||||||
|
((ostring*)_calc_stack.back())->_value[str_size] = 0;
|
||||||
void rpn_num()
|
|
||||||
{
|
_stack->pop_back();
|
||||||
MIN_ARGUMENTS(1);
|
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
_calc_stack.pop_back();
|
||||||
|
} else {
|
||||||
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0];
|
_stack->pop_back();
|
||||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
ostring* str =
|
||||||
numb->_value = the_chr;
|
(ostring*)_stack->allocate_back(1 + sizeof(ostring), cmd_string);
|
||||||
}
|
str->_len = 0;
|
||||||
|
str->_value[0] = 0;
|
||||||
void rpn_strsize()
|
}
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
||||||
|
|
||||||
double len = ((ostring*)_stack->pop_back())->_len;
|
|
||||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
numb->_value = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_strpos()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
|
||||||
|
|
||||||
long pos = 0;
|
|
||||||
char* src = ((ostring*)_stack->get_obj(1))->_value;
|
|
||||||
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
|
|
||||||
if (found != NULL)
|
|
||||||
pos = (long)(found - src)+1L;
|
|
||||||
|
|
||||||
_stack->pop_back(2);
|
|
||||||
|
|
||||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
numb->_value = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_strsub()
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(3);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
ARG_MUST_BE_OF_TYPE(2, cmd_string);
|
|
||||||
|
|
||||||
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
|
|
||||||
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
|
|
||||||
long len = ((ostring*)_stack->get_obj(2))->_len;
|
|
||||||
bool result_is_void = false;
|
|
||||||
|
|
||||||
_stack->pop_back(2);
|
|
||||||
|
|
||||||
if (first < 0)
|
|
||||||
first = 0;
|
|
||||||
if (last < 0)
|
|
||||||
last = 0;
|
|
||||||
if (first > len && last > len)
|
|
||||||
result_is_void=true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (first > len)
|
|
||||||
first = len -1;
|
|
||||||
if (last > len)
|
|
||||||
last = len -1;
|
|
||||||
if (first > last)
|
|
||||||
result_is_void=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result_is_void)
|
|
||||||
{
|
|
||||||
unsigned int str_size = last - first + 1;
|
|
||||||
ostring* str = (ostring*)_calc_stack.allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
|
||||||
str->_len = str_size;
|
|
||||||
|
|
||||||
memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->get_obj(0))->_value+first, str_size);
|
|
||||||
((ostring*)_calc_stack.back())->_value[str_size] = 0;
|
|
||||||
|
|
||||||
_stack->pop_back();
|
|
||||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
|
||||||
_calc_stack.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_stack->pop_back();
|
|
||||||
ostring* str = (ostring*)_stack->allocate_back(1+sizeof(ostring), cmd_string);
|
|
||||||
str->_len = 0;
|
|
||||||
str->_value[0] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,251 +1,223 @@
|
||||||
void test_get_stack(string& stack_is, stack& stk)
|
void test_get_stack(string& stack_is, stack& stk) {
|
||||||
{
|
// write stack in a string, each entry separated between commas
|
||||||
// write stack in a string, each entry separated between commas
|
for (int i = 0; i < (int)stk.size(); i++) {
|
||||||
for (int i = 0; i < (int)stk.size(); i++)
|
FILE* tmp_file = tmpfile();
|
||||||
{
|
char* line = NULL;
|
||||||
FILE* tmp_file = tmpfile();
|
size_t len;
|
||||||
char* line = NULL;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0) stack_is += ", ";
|
||||||
stack_is += ", ";
|
|
||||||
|
|
||||||
if (tmp_file != NULL)
|
if (tmp_file != NULL) {
|
||||||
{
|
((object*)stk.seq_obj(i))->show(tmp_file);
|
||||||
((object*)stk.seq_obj(i))->show(tmp_file);
|
|
||||||
|
|
||||||
// write stack in a tmp file
|
// write stack in a tmp file
|
||||||
(void)rewind(tmp_file);
|
(void)rewind(tmp_file);
|
||||||
if (getline(&line, &len, tmp_file) >=0)
|
if (getline(&line, &len, tmp_file) >= 0) {
|
||||||
{
|
stack_is += line;
|
||||||
stack_is += line;
|
free(line);
|
||||||
free(line);
|
}
|
||||||
}
|
(void)fclose(tmp_file);
|
||||||
(void)fclose(tmp_file);
|
} else
|
||||||
}
|
ERR_CONTEXT(ret_runtime_error);
|
||||||
else
|
}
|
||||||
ERR_CONTEXT(ret_runtime_error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed)
|
void test_show_result(string title, int tests, int tests_failed, int steps,
|
||||||
{
|
int steps_failed) {
|
||||||
printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests-tests_failed);
|
printf("%s: run %d tests: %d passed, ", title.c_str(), tests,
|
||||||
if(tests_failed>0)
|
tests - tests_failed);
|
||||||
printf(FG_RED);
|
if (tests_failed > 0) printf(FG_RED);
|
||||||
printf("%d failed", tests_failed);
|
printf("%d failed", tests_failed);
|
||||||
if(tests_failed>0)
|
if (tests_failed > 0) printf(COLOR_OFF);
|
||||||
printf(COLOR_OFF);
|
|
||||||
|
|
||||||
printf(" (%d steps: %d passed, ", steps, steps-steps_failed);
|
printf(" (%d steps: %d passed, ", steps, steps - steps_failed);
|
||||||
if(steps_failed>0)
|
if (steps_failed > 0) printf(FG_RED);
|
||||||
printf(FG_RED);
|
printf("%d failed", steps_failed);
|
||||||
printf("%d failed", steps_failed);
|
if (steps_failed > 0) printf(COLOR_OFF);
|
||||||
if(steps_failed>0)
|
printf(")\n");
|
||||||
printf(COLOR_OFF);
|
|
||||||
printf(")\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_test()
|
void rpn_test() {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
||||||
|
|
||||||
int total_tests=0;
|
int total_tests = 0;
|
||||||
int total_tests_failed=0;
|
int total_tests_failed = 0;
|
||||||
int total_steps=0;
|
int total_steps = 0;
|
||||||
int total_steps_failed=0;
|
int total_steps_failed = 0;
|
||||||
|
|
||||||
string test_filename = ((ostring*)_stack->pop_back())->_value;
|
string test_filename = ((ostring*)_stack->pop_back())->_value;
|
||||||
printf("\nrpn version is %s\n", version);
|
printf("\nrpn version is %s\n", version);
|
||||||
test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed);
|
test(test_filename, total_tests, total_tests_failed, total_steps,
|
||||||
test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed);
|
total_steps_failed);
|
||||||
|
test_show_result("Total", total_tests, total_tests_failed, total_steps,
|
||||||
|
total_steps_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed)
|
void test(string test_filename, int& total_tests, int& total_tests_failed,
|
||||||
{
|
int& total_steps, int& total_steps_failed) {
|
||||||
const string stack_size("-> stack size should be ");
|
const string stack_size("-> stack size should be ");
|
||||||
const string stack_value("-> stack should be ");
|
const string stack_value("-> stack should be ");
|
||||||
const string cmd_error("-> error should be ");
|
const string cmd_error("-> error should be ");
|
||||||
const string cmd_exit("exit test");
|
const string cmd_exit("exit test");
|
||||||
|
|
||||||
ifstream test_file(test_filename.c_str());
|
ifstream test_file(test_filename.c_str());
|
||||||
int tests = 0;
|
int tests = 0;
|
||||||
int tests_failed = 0;
|
int tests_failed = 0;
|
||||||
int steps = 0;
|
int steps = 0;
|
||||||
int steps_failed = 0;
|
int steps_failed = 0;
|
||||||
|
|
||||||
if (test_file.is_open())
|
if (test_file.is_open()) {
|
||||||
{
|
string test_title;
|
||||||
string test_title;
|
string entry;
|
||||||
string entry;
|
ret_value ret;
|
||||||
ret_value ret;
|
stack stk;
|
||||||
stack stk;
|
heap hp;
|
||||||
heap hp;
|
bool failed = false;
|
||||||
bool failed = false;
|
bool is_first_step;
|
||||||
bool is_first_step;
|
bool is_test_error_shown;
|
||||||
bool is_test_error_shown;
|
int last_err;
|
||||||
int last_err;
|
stringstream cerr_buffer;
|
||||||
stringstream cerr_buffer;
|
streambuf* cerr_old_buffer;
|
||||||
streambuf* cerr_old_buffer;
|
|
||||||
|
|
||||||
// redirect cerr
|
// redirect cerr
|
||||||
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
|
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
|
||||||
|
|
||||||
while (!test_file.eof())
|
while (!test_file.eof()) {
|
||||||
{
|
getline(test_file, entry);
|
||||||
getline(test_file, entry);
|
|
||||||
|
|
||||||
if (entry.substr(0,8)=="#include")
|
if (entry.substr(0, 8) == "#include")
|
||||||
test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed);
|
test(entry.substr(9), total_tests, total_tests_failed, total_steps,
|
||||||
else if (entry.substr(0,2)=="##")
|
total_steps_failed);
|
||||||
printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str());
|
else if (entry.substr(0, 2) == "##")
|
||||||
else if (entry.substr(0,2)=="# ")
|
printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str());
|
||||||
{
|
else if (entry.substr(0, 2) == "# ") {
|
||||||
// indicates the status of previous test
|
|
||||||
if (failed == false && tests > 0)
|
|
||||||
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
|
||||||
failed = false;
|
|
||||||
|
|
||||||
// read a test title
|
|
||||||
test_title = entry;
|
|
||||||
is_first_step = true;
|
|
||||||
is_test_error_shown = false;
|
|
||||||
printf("%s", test_title.c_str());
|
|
||||||
}
|
|
||||||
// treat "-> stack size should be "
|
|
||||||
else if (entry.find(stack_size, 0) == 0)
|
|
||||||
{
|
|
||||||
// count test and step
|
|
||||||
if (is_first_step)
|
|
||||||
tests++;
|
|
||||||
steps++;
|
|
||||||
|
|
||||||
// check current stack size
|
|
||||||
istringstream isub;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
isub.str(entry.substr(stack_size.size()));
|
|
||||||
isub>>size;
|
|
||||||
if (size != (int)stk.size())
|
|
||||||
{
|
|
||||||
// count fail test and step
|
|
||||||
if (!is_test_error_shown)
|
|
||||||
{
|
|
||||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
|
||||||
tests_failed++;
|
|
||||||
is_test_error_shown = true;
|
|
||||||
}
|
|
||||||
steps_failed++;
|
|
||||||
|
|
||||||
// show failure
|
|
||||||
printf("\t%s\n", entry.c_str());
|
|
||||||
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n", stk.size());
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
is_first_step = false;
|
|
||||||
}
|
|
||||||
// treat "-> stack should be "
|
|
||||||
else if (entry.find(stack_value, 0) == 0)
|
|
||||||
{
|
|
||||||
// count test
|
|
||||||
if (is_first_step)
|
|
||||||
tests++;
|
|
||||||
steps++;
|
|
||||||
|
|
||||||
// check current stack value
|
|
||||||
string stack_should_be = entry.substr(stack_value.size());
|
|
||||||
string stack_is;
|
|
||||||
|
|
||||||
test_get_stack(stack_is, stk);
|
|
||||||
|
|
||||||
if (stack_is != stack_should_be)
|
|
||||||
{
|
|
||||||
// count fail test and step
|
|
||||||
if (!is_test_error_shown)
|
|
||||||
{
|
|
||||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
|
||||||
tests_failed++;
|
|
||||||
is_test_error_shown = true;
|
|
||||||
}
|
|
||||||
steps_failed++;
|
|
||||||
|
|
||||||
// show failure
|
|
||||||
printf("\t%s\n", entry.c_str());
|
|
||||||
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n", stack_is.c_str());
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
is_first_step = false;
|
|
||||||
}
|
|
||||||
// treat "-> error should be "
|
|
||||||
else if (entry.find(cmd_error, 0) == 0)
|
|
||||||
{
|
|
||||||
// count test
|
|
||||||
if (is_first_step)
|
|
||||||
tests++;
|
|
||||||
steps++;
|
|
||||||
|
|
||||||
// check current error
|
|
||||||
istringstream isub;
|
|
||||||
int err_should_be;
|
|
||||||
isub.str(entry.substr(cmd_error.size()));
|
|
||||||
isub>>err_should_be;
|
|
||||||
if (err_should_be != last_err)
|
|
||||||
{
|
|
||||||
// count fail test and step
|
|
||||||
if (!is_test_error_shown)
|
|
||||||
{
|
|
||||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
|
||||||
tests_failed++;
|
|
||||||
is_test_error_shown = true;
|
|
||||||
}
|
|
||||||
steps_failed++;
|
|
||||||
|
|
||||||
// show failure
|
|
||||||
printf("\t%s\n", entry.c_str());
|
|
||||||
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
is_first_step = false;
|
|
||||||
}
|
|
||||||
else if (entry.find(cmd_exit, 0) == 0)
|
|
||||||
{
|
|
||||||
// forced test end
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (entry.size() > 0)
|
|
||||||
{
|
|
||||||
// parse entry and run line
|
|
||||||
program prog;
|
|
||||||
ret = program::parse(entry.c_str(), prog);
|
|
||||||
if (ret == ret_ok)
|
|
||||||
{
|
|
||||||
// run it
|
|
||||||
(void)prog.run(stk, hp);
|
|
||||||
last_err = (int)prog.get_err();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// last test
|
|
||||||
// indicates the status of previous test
|
// indicates the status of previous test
|
||||||
if (failed == false && tests > 0)
|
if (failed == false && tests > 0)
|
||||||
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||||
|
failed = false;
|
||||||
|
|
||||||
// cerr back
|
// read a test title
|
||||||
cerr.rdbuf(cerr_old_buffer);
|
test_title = entry;
|
||||||
|
is_first_step = true;
|
||||||
|
is_test_error_shown = false;
|
||||||
|
printf("%s", test_title.c_str());
|
||||||
|
}
|
||||||
|
// treat "-> stack size should be "
|
||||||
|
else if (entry.find(stack_size, 0) == 0) {
|
||||||
|
// count test and step
|
||||||
|
if (is_first_step) tests++;
|
||||||
|
steps++;
|
||||||
|
|
||||||
// conclusion: show and keep for total
|
// check current stack size
|
||||||
if (tests != 0)
|
istringstream isub;
|
||||||
{
|
int size;
|
||||||
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
|
|
||||||
|
|
||||||
total_tests += tests;
|
isub.str(entry.substr(stack_size.size()));
|
||||||
total_tests_failed += tests_failed;
|
isub >> size;
|
||||||
total_steps += steps;
|
if (size != (int)stk.size()) {
|
||||||
total_steps_failed += steps_failed;
|
// count fail test and step
|
||||||
|
if (!is_test_error_shown) {
|
||||||
|
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||||
|
tests_failed++;
|
||||||
|
is_test_error_shown = true;
|
||||||
|
}
|
||||||
|
steps_failed++;
|
||||||
|
|
||||||
|
// show failure
|
||||||
|
printf("\t%s\n", entry.c_str());
|
||||||
|
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n",
|
||||||
|
stk.size());
|
||||||
|
failed = true;
|
||||||
}
|
}
|
||||||
|
is_first_step = false;
|
||||||
|
}
|
||||||
|
// treat "-> stack should be "
|
||||||
|
else if (entry.find(stack_value, 0) == 0) {
|
||||||
|
// count test
|
||||||
|
if (is_first_step) tests++;
|
||||||
|
steps++;
|
||||||
|
|
||||||
|
// check current stack value
|
||||||
|
string stack_should_be = entry.substr(stack_value.size());
|
||||||
|
string stack_is;
|
||||||
|
|
||||||
|
test_get_stack(stack_is, stk);
|
||||||
|
|
||||||
|
if (stack_is != stack_should_be) {
|
||||||
|
// count fail test and step
|
||||||
|
if (!is_test_error_shown) {
|
||||||
|
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||||
|
tests_failed++;
|
||||||
|
is_test_error_shown = true;
|
||||||
|
}
|
||||||
|
steps_failed++;
|
||||||
|
|
||||||
|
// show failure
|
||||||
|
printf("\t%s\n", entry.c_str());
|
||||||
|
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n",
|
||||||
|
stack_is.c_str());
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
is_first_step = false;
|
||||||
|
}
|
||||||
|
// treat "-> error should be "
|
||||||
|
else if (entry.find(cmd_error, 0) == 0) {
|
||||||
|
// count test
|
||||||
|
if (is_first_step) tests++;
|
||||||
|
steps++;
|
||||||
|
|
||||||
|
// check current error
|
||||||
|
istringstream isub;
|
||||||
|
int err_should_be;
|
||||||
|
isub.str(entry.substr(cmd_error.size()));
|
||||||
|
isub >> err_should_be;
|
||||||
|
if (err_should_be != last_err) {
|
||||||
|
// count fail test and step
|
||||||
|
if (!is_test_error_shown) {
|
||||||
|
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||||
|
tests_failed++;
|
||||||
|
is_test_error_shown = true;
|
||||||
|
}
|
||||||
|
steps_failed++;
|
||||||
|
|
||||||
|
// show failure
|
||||||
|
printf("\t%s\n", entry.c_str());
|
||||||
|
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
is_first_step = false;
|
||||||
|
} else if (entry.find(cmd_exit, 0) == 0) {
|
||||||
|
// forced test end
|
||||||
|
break;
|
||||||
|
} else if (entry.size() > 0) {
|
||||||
|
// parse entry and run line
|
||||||
|
program prog;
|
||||||
|
ret = program::parse(entry.c_str(), prog);
|
||||||
|
if (ret == ret_ok) {
|
||||||
|
// run it
|
||||||
|
(void)prog.run(stk, hp);
|
||||||
|
last_err = (int)prog.get_err();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str());
|
// last test
|
||||||
|
// indicates the status of previous test
|
||||||
|
if (failed == false && tests > 0) printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||||
|
|
||||||
|
// cerr back
|
||||||
|
cerr.rdbuf(cerr_old_buffer);
|
||||||
|
|
||||||
|
// conclusion: show and keep for total
|
||||||
|
if (tests != 0) {
|
||||||
|
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
|
||||||
|
|
||||||
|
total_tests += tests;
|
||||||
|
total_tests_failed += tests_failed;
|
||||||
|
total_steps += steps;
|
||||||
|
total_steps_failed += steps_failed;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
469
src/rpn-test.hpp
469
src/rpn-test.hpp
|
@ -1,270 +1,251 @@
|
||||||
int cmp_strings_on_stack_top()
|
int cmp_strings_on_stack_top() {
|
||||||
{
|
// _stack sould have 2 strings at level 1 and 2
|
||||||
// _stack sould have 2 strings at level 1 and 2
|
// this function removes these 2 entries
|
||||||
// this function removes these 2 entries
|
ostring* right = (ostring*)_stack->pop_back();
|
||||||
ostring* right = (ostring*)_stack->pop_back();
|
ostring* left = (ostring*)_stack->pop_back();
|
||||||
ostring* left = (ostring*)_stack->pop_back();
|
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
|
||||||
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_sup(void)
|
void rpn_sup(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
// numbers
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
{
|
number* right = (number*)_stack->pop_back();
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp > 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_sup_eq(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp >= 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_inf(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp < 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_inf_eq(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp <= 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_diff(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// complexes
|
|
||||||
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
|
|
||||||
{
|
|
||||||
bool diff = false;
|
|
||||||
complex* right = (complex*)_stack->pop_back();
|
|
||||||
complex* left = (complex*)_stack->pop_back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
|
||||||
diff = true;
|
|
||||||
|
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
if (diff)
|
|
||||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp != 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_eq(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
|
|
||||||
// numbers
|
|
||||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
|
||||||
{
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// complexes
|
|
||||||
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
|
|
||||||
{
|
|
||||||
bool diff = false;
|
|
||||||
complex* right = (complex*)_stack->pop_back();
|
|
||||||
complex* left = (complex*)_stack->pop_back();
|
|
||||||
|
|
||||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
|
||||||
diff = true;
|
|
||||||
|
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
if (diff)
|
|
||||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
// strings
|
|
||||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
|
||||||
{
|
|
||||||
int res_cmp = cmp_strings_on_stack_top();
|
|
||||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
res->_value = (res_cmp == 0) ? 1L : 0L;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_test_and(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
|
|
||||||
number* right = (number*)_stack->pop_back();
|
|
||||||
number* left = (number*)_stack->back();
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
|
||||||
&& (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
else
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
|
_stack->get_type(1) == cmd_string) {
|
||||||
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp > 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_test_or(void)
|
void rpn_sup_eq(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
|
|
||||||
number* right = (number*)_stack->pop_back();
|
// numbers
|
||||||
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
number* left = (number*)_stack->back();
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
|
||||||
|| (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
else
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
|
_stack->get_type(1) == cmd_string) {
|
||||||
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp >= 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_test_xor(void)
|
void rpn_inf(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(2);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
|
||||||
|
|
||||||
number* right = (number*)_stack->pop_back();
|
// numbers
|
||||||
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
number* left = (number*)_stack->back();
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
|
||||||
{
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
|
||||||
else
|
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
|
}
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
// strings
|
||||||
else
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
_stack->get_type(1) == cmd_string) {
|
||||||
}
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp < 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_test_not(void)
|
void rpn_inf_eq(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
|
// numbers
|
||||||
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
number* left = (number*)_stack->back();
|
number* left = (number*)_stack->back();
|
||||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
|
||||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
else
|
else
|
||||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
|
_stack->get_type(1) == cmd_string) {
|
||||||
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp <= 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_same(void)
|
void rpn_diff(void) {
|
||||||
{
|
MIN_ARGUMENTS(2);
|
||||||
rpn_eq();
|
|
||||||
|
// numbers
|
||||||
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// complexes
|
||||||
|
else if (_stack->get_type(0) == cmd_complex &&
|
||||||
|
_stack->get_type(1) == cmd_complex) {
|
||||||
|
bool diff = false;
|
||||||
|
complex* right = (complex*)_stack->pop_back();
|
||||||
|
complex* left = (complex*)_stack->pop_back();
|
||||||
|
|
||||||
|
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
|
||||||
|
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||||
|
diff = true;
|
||||||
|
|
||||||
|
number* num =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
if (diff)
|
||||||
|
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
|
_stack->get_type(1) == cmd_string) {
|
||||||
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp != 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rpn_eq(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
|
||||||
|
// numbers
|
||||||
|
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
|
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// complexes
|
||||||
|
else if (_stack->get_type(0) == cmd_complex &&
|
||||||
|
_stack->get_type(1) == cmd_complex) {
|
||||||
|
bool diff = false;
|
||||||
|
complex* right = (complex*)_stack->pop_back();
|
||||||
|
complex* left = (complex*)_stack->pop_back();
|
||||||
|
|
||||||
|
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
|
||||||
|
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||||
|
diff = true;
|
||||||
|
|
||||||
|
number* num =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
if (diff)
|
||||||
|
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
else if (_stack->get_type(0) == cmd_string &&
|
||||||
|
_stack->get_type(1) == cmd_string) {
|
||||||
|
int res_cmp = cmp_strings_on_stack_top();
|
||||||
|
number* res =
|
||||||
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
res->_value = (res_cmp == 0) ? 1L : 0L;
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_test_and(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
|
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
|
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) &&
|
||||||
|
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_test_or(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
|
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
|
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) ||
|
||||||
|
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_test_xor(void) {
|
||||||
|
MIN_ARGUMENTS(2);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||||
|
|
||||||
|
number* right = (number*)_stack->pop_back();
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
|
||||||
|
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0) {
|
||||||
|
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
} else {
|
||||||
|
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_test_not(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
number* left = (number*)_stack->back();
|
||||||
|
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
||||||
|
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||||
|
else
|
||||||
|
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_same(void) { rpn_eq(); }
|
||||||
|
|
444
src/rpn-trig.hpp
444
src/rpn-trig.hpp
|
@ -1,263 +1,239 @@
|
||||||
//
|
//
|
||||||
void rpn_pi(void)
|
void rpn_pi(void) {
|
||||||
{
|
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_d2r(void)
|
void rpn_d2r(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
// add pi on stack
|
// add pi on stack
|
||||||
rpn_pi();
|
rpn_pi();
|
||||||
|
|
||||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||||
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
|
|
||||||
|
CHECK_MPFR(
|
||||||
|
mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_r2d(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||||
|
|
||||||
|
// add pi on stack
|
||||||
|
rpn_pi();
|
||||||
|
|
||||||
|
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||||
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
|
|
||||||
|
CHECK_MPFR(
|
||||||
|
mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpn_sin(void) {
|
||||||
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
|
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
// sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
|
||||||
|
floating_t* tmp =
|
||||||
|
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||||
|
->_value;
|
||||||
|
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||||
|
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||||
|
|
||||||
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
|
|
||||||
|
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
_calc_stack.pop_back(2);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_r2d(void)
|
void rpn_asin(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
|
||||||
|
|
||||||
// add pi on stack
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
rpn_pi();
|
|
||||||
|
|
||||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
|
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
number* num;
|
||||||
|
complex* i;
|
||||||
|
|
||||||
|
// asin(z)=-iln(iz+sqrt(1-z*z))
|
||||||
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
|
|
||||||
|
i = (complex*)_calc_stack.get_obj(0);
|
||||||
|
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
rpn_dup();
|
||||||
|
rpn_square();
|
||||||
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
|
rpn_minus();
|
||||||
|
rpn_neg();
|
||||||
|
rpn_squareroot();
|
||||||
|
rpn_swap();
|
||||||
|
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||||
|
rpn_mul();
|
||||||
|
rpn_plus();
|
||||||
|
rpn_ln();
|
||||||
|
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||||
|
rpn_mul();
|
||||||
|
rpn_neg();
|
||||||
|
_calc_stack.pop_back();
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_sin(void)
|
void rpn_cos(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
{
|
|
||||||
// sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* tmp =
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||||
|
->_value;
|
||||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
_calc_stack.pop_back(2);
|
CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
}
|
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
else
|
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
|
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
_calc_stack.pop_back(2);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_asin(void)
|
void rpn_acos(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// acos(z)=pi/2-asin(z)
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
rpn_asin();
|
||||||
{
|
rpn_pi();
|
||||||
number* num;
|
number* num =
|
||||||
complex* i;
|
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||||
//asin(z)=-iln(iz+sqrt(1-z*z))
|
rpn_div();
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
rpn_minus();
|
||||||
|
rpn_neg();
|
||||||
i = (complex*)_calc_stack.get_obj(0);
|
} else
|
||||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
rpn_dup();
|
|
||||||
rpn_square();
|
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
|
||||||
rpn_minus();
|
|
||||||
rpn_neg();
|
|
||||||
rpn_squareroot();
|
|
||||||
rpn_swap();
|
|
||||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
|
||||||
rpn_mul();
|
|
||||||
rpn_plus();
|
|
||||||
rpn_ln();
|
|
||||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
|
||||||
rpn_mul();
|
|
||||||
rpn_neg();
|
|
||||||
_calc_stack.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_cos(void)
|
void rpn_tan(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
// tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
{
|
|
||||||
// cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
floating_t* tmp =
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||||
|
->_value;
|
||||||
CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
_calc_stack.pop_back(2);
|
// x->2x
|
||||||
}
|
CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||||
else
|
// y->2y
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
// sin(2x)+sinh(2y)
|
||||||
|
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
// cosh(2y)+cos(2x)
|
||||||
|
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
// sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
|
||||||
|
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||||
|
|
||||||
|
_calc_stack.pop_back(2);
|
||||||
|
} else
|
||||||
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_acos(void)
|
void rpn_atan(void) {
|
||||||
{
|
MIN_ARGUMENTS(1);
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
if (_stack->get_type(0) == cmd_number) {
|
||||||
{
|
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||||
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
} else if (_stack->get_type(0) == cmd_complex) {
|
||||||
}
|
number* num;
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
complex* i;
|
||||||
{
|
|
||||||
//acos(z)=pi/2-asin(z)
|
// atan(z)=0.5i(ln((1-iz)/(1+iz))
|
||||||
rpn_asin();
|
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||||
rpn_pi();
|
|
||||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
i = (complex*)_calc_stack.get_obj(0);
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_div();
|
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
rpn_minus();
|
|
||||||
rpn_neg();
|
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||||
}
|
rpn_mul();
|
||||||
else
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||||
}
|
rpn_minus(); // iz-1
|
||||||
|
rpn_neg(); // 1-iz
|
||||||
void rpn_tan(void)
|
rpn_dup();
|
||||||
{
|
rpn_neg(); // iz-1
|
||||||
MIN_ARGUMENTS(1);
|
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||||
|
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||||
if (_stack->get_type(0) == cmd_number)
|
rpn_plus(); // iz+1
|
||||||
{
|
rpn_div();
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
|
||||||
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
rpn_ln();
|
||||||
}
|
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||||
{
|
rpn_mul();
|
||||||
// tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
_calc_stack.pop_back();
|
||||||
|
} else
|
||||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
ERR_CONTEXT(ret_bad_operand_type);
|
||||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
|
||||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
|
||||||
|
|
||||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
|
||||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
|
||||||
|
|
||||||
//x->2x
|
|
||||||
CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
|
|
||||||
//y->2y
|
|
||||||
CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
//sin(2x)+sinh(2y)
|
|
||||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
//cosh(2y)+cos(2x)
|
|
||||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
//sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
|
|
||||||
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
_calc_stack.pop_back(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpn_atan(void)
|
|
||||||
{
|
|
||||||
MIN_ARGUMENTS(1);
|
|
||||||
|
|
||||||
if (_stack->get_type(0) == cmd_number)
|
|
||||||
{
|
|
||||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
|
||||||
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
|
||||||
}
|
|
||||||
else if (_stack->get_type(0) == cmd_complex)
|
|
||||||
{
|
|
||||||
number* num;
|
|
||||||
complex* i;
|
|
||||||
|
|
||||||
//atan(z)=0.5i(ln((1-iz)/(1+iz))
|
|
||||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
|
||||||
|
|
||||||
i = (complex*)_calc_stack.get_obj(0);
|
|
||||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
|
||||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
|
||||||
|
|
||||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
|
||||||
rpn_mul();
|
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
|
||||||
rpn_minus();//iz-1
|
|
||||||
rpn_neg();//1-iz
|
|
||||||
rpn_dup();
|
|
||||||
rpn_neg();//iz-1
|
|
||||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
|
||||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
|
||||||
rpn_plus();//iz+1
|
|
||||||
rpn_div();
|
|
||||||
|
|
||||||
rpn_ln();
|
|
||||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
|
||||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
|
||||||
rpn_mul();
|
|
||||||
|
|
||||||
_calc_stack.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ERR_CONTEXT(ret_bad_operand_type);
|
|
||||||
}
|
}
|
||||||
|
|
513
src/stack.hpp
513
src/stack.hpp
|
@ -6,326 +6,281 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// allocation base size
|
// allocation base size
|
||||||
#define ALLOC_STACK_CHUNK (64*1024)
|
#define ALLOC_STACK_CHUNK (64 * 1024)
|
||||||
|
|
||||||
//
|
//
|
||||||
class stack
|
class stack {
|
||||||
{
|
public:
|
||||||
public:
|
stack() {
|
||||||
stack()
|
_base = NULL;
|
||||||
{
|
_base_pointer = NULL;
|
||||||
_base = NULL;
|
_total_size = 0;
|
||||||
_base_pointer = NULL;
|
_total_count_pointer = 0;
|
||||||
_total_size = 0;
|
erase();
|
||||||
_total_count_pointer = 0;
|
}
|
||||||
erase();
|
|
||||||
|
virtual ~stack() {
|
||||||
|
if (_base != NULL) free(_base);
|
||||||
|
if (_base_pointer != NULL) free(_base_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase() {
|
||||||
|
_current = _base;
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
static void copy_and_push_back(stack& from, unsigned int index_from,
|
||||||
|
stack& to) {
|
||||||
|
// copy a whole stack entry and push it back to another stack
|
||||||
|
object* allocated =
|
||||||
|
to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
|
||||||
|
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
|
||||||
|
|
||||||
|
if (allocated->_type == cmd_number)
|
||||||
|
((number*)allocated)->move();
|
||||||
|
else if (allocated->_type == cmd_complex)
|
||||||
|
((complex*)allocated)->move();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
static void copy_and_push_back(object* from, stack& to, unsigned int size) {
|
||||||
|
// copy a whole stack entry and push it back to another stack
|
||||||
|
object* allocated = to.allocate_back(size, from->_type);
|
||||||
|
memcpy(allocated, from, size);
|
||||||
|
|
||||||
|
if (allocated->_type == cmd_number)
|
||||||
|
((number*)allocated)->move();
|
||||||
|
else if (allocated->_type == cmd_complex)
|
||||||
|
((complex*)allocated)->move();
|
||||||
|
}
|
||||||
|
|
||||||
|
object* allocate_back(unsigned int size, cmd_type_t type) {
|
||||||
|
object* allocated;
|
||||||
|
bool data_is_reallocated = false;
|
||||||
|
char* old_base;
|
||||||
|
|
||||||
|
// manage data memory allocation (add as much as memory it is needed)
|
||||||
|
if (((_current - _base) + size) > _total_size) {
|
||||||
|
// calc nb of needed pages
|
||||||
|
unsigned long page_number =
|
||||||
|
1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
|
||||||
|
_total_size += page_number * ALLOC_STACK_CHUNK;
|
||||||
|
|
||||||
|
old_base = _base;
|
||||||
|
_base = (char*)realloc(_base, _total_size);
|
||||||
|
|
||||||
|
_current = _base + (_current - old_base);
|
||||||
|
data_is_reallocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~stack()
|
// manage pointers memory allocation (add one page if needed)
|
||||||
{
|
if ((_count + 1) > _total_count_pointer) {
|
||||||
if (_base != NULL)
|
_base_pointer = (object**)realloc(
|
||||||
free(_base);
|
_base_pointer,
|
||||||
if (_base_pointer != NULL)
|
(_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
|
||||||
free(_base_pointer);
|
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase()
|
// recalc object pointers in case of base reallocation
|
||||||
{
|
if (data_is_reallocated) {
|
||||||
_current = _base;
|
for (int i = 0; i < _count; i++) {
|
||||||
_count = 0;
|
_base_pointer[i] =
|
||||||
|
(object*)(_base + ((char*)_base_pointer[i] - old_base));
|
||||||
|
if (_base_pointer[i]->_type == cmd_number)
|
||||||
|
((number*)_base_pointer[i])->move();
|
||||||
|
else if (_base_pointer[i]->_type == cmd_complex)
|
||||||
|
((complex*)_base_pointer[i])->move();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// manage stack itself
|
||||||
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to)
|
_base_pointer[_count++] = (object*)_current;
|
||||||
{
|
allocated = (object*)_current;
|
||||||
// copy a whole stack entry and push it back to another stack
|
_current += size;
|
||||||
object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
|
|
||||||
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
|
|
||||||
|
|
||||||
if (allocated->_type == cmd_number)
|
// init object
|
||||||
((number*)allocated)->move();
|
allocated->_type = type;
|
||||||
else if (allocated->_type == cmd_complex)
|
allocated->_size = size;
|
||||||
((complex*)allocated)->move();
|
if (type == cmd_number)
|
||||||
|
((number*)allocated)->init();
|
||||||
|
else if (type == cmd_complex)
|
||||||
|
((complex*)allocated)->init();
|
||||||
|
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
object* pop_back(int pop_count = 1) {
|
||||||
|
object* back = NULL;
|
||||||
|
|
||||||
|
// pop several entries, return the last
|
||||||
|
while (pop_count-- > 0) {
|
||||||
|
if (_count > 0) {
|
||||||
|
_current = (char*)_base_pointer[--_count];
|
||||||
|
back = (object*)_current;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
return back;
|
||||||
static void copy_and_push_back(object* from, stack& to, unsigned int size)
|
}
|
||||||
{
|
|
||||||
// copy a whole stack entry and push it back to another stack
|
|
||||||
object* allocated = to.allocate_back(size, from->_type);
|
|
||||||
memcpy(allocated, from, size);
|
|
||||||
|
|
||||||
if (allocated->_type == cmd_number)
|
unsigned int size() { return _count; }
|
||||||
((number*)allocated)->move();
|
|
||||||
else if (allocated->_type == cmd_complex)
|
|
||||||
((complex*)allocated)->move();
|
|
||||||
}
|
|
||||||
|
|
||||||
object* allocate_back(unsigned int size, cmd_type_t type)
|
|
||||||
{
|
|
||||||
object* allocated;
|
|
||||||
bool data_is_reallocated = false;
|
|
||||||
char* old_base;
|
|
||||||
|
|
||||||
// manage data memory allocation (add as much as memory it is needed)
|
// stack access (stack_level=0=first out)
|
||||||
if (((_current - _base) + size) > _total_size)
|
object* get_obj(unsigned int stack_level) {
|
||||||
{
|
return seq_obj(_count - stack_level - 1);
|
||||||
// calc nb of needed pages
|
}
|
||||||
unsigned long page_number = 1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
|
|
||||||
_total_size += page_number * ALLOC_STACK_CHUNK;
|
|
||||||
|
|
||||||
old_base = _base;
|
object* operator[](unsigned int stack_level) {
|
||||||
_base = (char*)realloc(_base, _total_size);
|
return seq_obj(_count - stack_level - 1);
|
||||||
|
}
|
||||||
|
|
||||||
_current = _base + (_current - old_base);
|
object* back() {
|
||||||
data_is_reallocated = true;
|
object* obj = NULL;
|
||||||
}
|
if (_count > 0) obj = _base_pointer[_count - 1];
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
// manage pointers memory allocation (add one page if needed)
|
unsigned int get_len(unsigned int index) {
|
||||||
if ((_count + 1) > _total_count_pointer)
|
return seq_len(_count - index - 1);
|
||||||
{
|
}
|
||||||
_base_pointer = (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
|
|
||||||
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
|
|
||||||
}
|
|
||||||
|
|
||||||
// recalc object pointers in case of base reallocation
|
cmd_type_t get_type(unsigned int index) {
|
||||||
if (data_is_reallocated)
|
return seq_type(_count - index - 1);
|
||||||
{
|
}
|
||||||
for(int i = 0; i < _count; i++)
|
|
||||||
{
|
|
||||||
_base_pointer[i] = (object*)(_base + ((char*)_base_pointer[i] - old_base));
|
|
||||||
if (_base_pointer[i]->_type == cmd_number)
|
|
||||||
((number*)_base_pointer[i])->move();
|
|
||||||
else if (_base_pointer[i]->_type == cmd_complex)
|
|
||||||
((complex*)_base_pointer[i])->move();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// manage stack itself
|
// sequential access (index is counted from front)
|
||||||
_base_pointer[_count++] = (object*)_current;
|
object* seq_obj(unsigned int index) {
|
||||||
allocated = (object*)_current;
|
object* obj = NULL;
|
||||||
_current += size;
|
if (index < _count) obj = _base_pointer[index];
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
// init object
|
unsigned int seq_len(unsigned int index) {
|
||||||
allocated->_type = type;
|
unsigned int len = 0;
|
||||||
allocated->_size = size;
|
if (index < _count) len = _base_pointer[index]->_size;
|
||||||
if (type == cmd_number)
|
return len;
|
||||||
((number*)allocated)->init();
|
}
|
||||||
else if (type == cmd_complex)
|
|
||||||
((complex*)allocated)->init();
|
|
||||||
|
|
||||||
return allocated;
|
cmd_type_t seq_type(unsigned int index) {
|
||||||
}
|
cmd_type_t type = cmd_undef;
|
||||||
|
if (index < _count) type = _base_pointer[index]->_type;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
object* pop_back(int pop_count = 1)
|
private:
|
||||||
{
|
char* _base;
|
||||||
object* back = NULL;
|
char* _current;
|
||||||
|
object** _base_pointer;
|
||||||
|
|
||||||
// pop several entries, return the last
|
unsigned int _count; // stack count
|
||||||
while (pop_count-- > 0)
|
unsigned int _total_count_pointer; // total number of possible pointers
|
||||||
{
|
unsigned int _total_size; // total allocated data size in bytes
|
||||||
if (_count > 0)
|
|
||||||
{
|
|
||||||
_current = (char*)_base_pointer[--_count];
|
|
||||||
back = (object*)_current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return back;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int size()
|
|
||||||
{
|
|
||||||
return _count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack access (stack_level=0=first out)
|
|
||||||
object* get_obj(unsigned int stack_level)
|
|
||||||
{
|
|
||||||
return seq_obj(_count - stack_level - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
object* operator[](unsigned int stack_level)
|
|
||||||
{
|
|
||||||
return seq_obj(_count - stack_level - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
object* back()
|
|
||||||
{
|
|
||||||
object* obj = NULL;
|
|
||||||
if (_count>0)
|
|
||||||
obj = _base_pointer[_count - 1];
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int get_len(unsigned int index)
|
|
||||||
{
|
|
||||||
return seq_len(_count - index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_type_t get_type(unsigned int index)
|
|
||||||
{
|
|
||||||
return seq_type(_count - index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sequential access (index is counted from front)
|
|
||||||
object* seq_obj(unsigned int index)
|
|
||||||
{
|
|
||||||
object* obj = NULL;
|
|
||||||
if (index<_count)
|
|
||||||
obj = _base_pointer[index];
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int seq_len(unsigned int index)
|
|
||||||
{
|
|
||||||
unsigned int len = 0;
|
|
||||||
if (index<_count)
|
|
||||||
len = _base_pointer[index]->_size;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_type_t seq_type(unsigned int index)
|
|
||||||
{
|
|
||||||
cmd_type_t type = cmd_undef;
|
|
||||||
if (index<_count)
|
|
||||||
type = _base_pointer[index]->_type;
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
char* _base;
|
|
||||||
char* _current;
|
|
||||||
object** _base_pointer;
|
|
||||||
|
|
||||||
unsigned int _count;//stack count
|
|
||||||
unsigned int _total_count_pointer;//total number of possible pointers
|
|
||||||
unsigned int _total_size;//total allocated data size in bytes
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
class heap : public stack
|
class heap : public stack {
|
||||||
{
|
public:
|
||||||
public:
|
heap() {}
|
||||||
heap() { }
|
virtual ~heap() {}
|
||||||
virtual ~heap() { }
|
|
||||||
|
|
||||||
object* add(const string name, object* obj, unsigned int size)
|
object* add(const string name, object* obj, unsigned int size) {
|
||||||
{
|
map<string, unsigned int>::iterator i = _map.find(name);
|
||||||
map<string, unsigned int>::iterator i = _map.find(name);
|
object* local = NULL;
|
||||||
object* local = NULL;
|
|
||||||
|
|
||||||
// variable does not exist in heap or already exists but its size is too short -> allocate
|
// variable does not exist in heap or already exists but its size is too
|
||||||
if (i!=_map.end())
|
// short -> allocate
|
||||||
local = seq_obj(i->second);
|
if (i != _map.end()) local = seq_obj(i->second);
|
||||||
|
|
||||||
if (local==NULL || (local!=NULL && size>local->_size))
|
if (local == NULL || (local != NULL && size > local->_size)) {
|
||||||
{
|
copy_and_push_back(obj, *this, size);
|
||||||
copy_and_push_back(obj, *this, size);
|
_map[name] = ((stack*)this)->size() - 1;
|
||||||
_map[name] = ((stack*)this)->size()-1;
|
} else {
|
||||||
}
|
// variable already exists in heap but previous was larger -> don't
|
||||||
else
|
// reallocate copy a whole stack entry and push it back to another stack
|
||||||
{
|
memcpy(local, obj, size);
|
||||||
// variable already exists in heap but previous was larger -> don't reallocate
|
if (local->_type == cmd_number)
|
||||||
// copy a whole stack entry and push it back to another stack
|
((number*)local)->move();
|
||||||
memcpy(local, obj, size);
|
else if (local->_type == cmd_complex)
|
||||||
if (local->_type == cmd_number)
|
((complex*)local)->move();
|
||||||
((number*)local)->move();
|
|
||||||
else if (local->_type == cmd_complex)
|
|
||||||
((complex*)local)->move();
|
|
||||||
}
|
|
||||||
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get(const string name, object*& obj, unsigned int& size)
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
map<string, unsigned int>::iterator i = _map.find(name);
|
|
||||||
|
|
||||||
if (i!=_map.end())
|
|
||||||
{
|
|
||||||
obj = seq_obj(i->second);
|
|
||||||
size = obj->_size;
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool replace_value(const string name, object* obj, unsigned int size)
|
return local;
|
||||||
{
|
}
|
||||||
bool ret=false;
|
|
||||||
map<string, unsigned int>::iterator i = _map.find(name);
|
|
||||||
|
|
||||||
if (i!=_map.end())
|
bool get(const string name, object*& obj, unsigned int& size) {
|
||||||
{
|
bool ret = false;
|
||||||
object* obj_dst = seq_obj(i->second);
|
map<string, unsigned int>::iterator i = _map.find(name);
|
||||||
if (size<=obj_dst->_size)
|
|
||||||
{
|
if (i != _map.end()) {
|
||||||
(void)memcpy(obj_dst, obj, size);
|
obj = seq_obj(i->second);
|
||||||
if (obj_dst->_type == cmd_number)
|
size = obj->_size;
|
||||||
((number*)obj_dst)->move();
|
ret = true;
|
||||||
else if (obj_dst->_type == cmd_complex)
|
|
||||||
((complex*)obj_dst)->move();
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool exist(const string name)
|
bool replace_value(const string name, object* obj, unsigned int size) {
|
||||||
{
|
bool ret = false;
|
||||||
return (_map.find(name) != _map.end());
|
map<string, unsigned int>::iterator i = _map.find(name);
|
||||||
|
|
||||||
|
if (i != _map.end()) {
|
||||||
|
object* obj_dst = seq_obj(i->second);
|
||||||
|
if (size <= obj_dst->_size) {
|
||||||
|
(void)memcpy(obj_dst, obj, size);
|
||||||
|
if (obj_dst->_type == cmd_number)
|
||||||
|
((number*)obj_dst)->move();
|
||||||
|
else if (obj_dst->_type == cmd_complex)
|
||||||
|
((complex*)obj_dst)->move();
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool get_by_index(int num, string& name, object*& obj, unsigned int& size)
|
bool exist(const string name) { return (_map.find(name) != _map.end()); }
|
||||||
{
|
|
||||||
if (num>=0 && num<(int)_map.size())
|
|
||||||
{
|
|
||||||
object* local;
|
|
||||||
map<string, unsigned int>::iterator i= _map.begin();
|
|
||||||
|
|
||||||
for(int j = 0; j < num; j++)
|
bool get_by_index(int num, string& name, object*& obj, unsigned int& size) {
|
||||||
i++;
|
if (num >= 0 && num < (int)_map.size()) {
|
||||||
|
object* local;
|
||||||
|
map<string, unsigned int>::iterator i = _map.begin();
|
||||||
|
|
||||||
local = (object*)seq_obj(i->second);
|
for (int j = 0; j < num; j++) i++;
|
||||||
name = i->first;
|
|
||||||
obj = local;
|
local = (object*)seq_obj(i->second);
|
||||||
size = local->_size;
|
name = i->first;
|
||||||
return true;
|
obj = local;
|
||||||
}
|
size = local->_size;
|
||||||
else
|
return true;
|
||||||
return false;
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool erase(const string& name) {
|
||||||
|
map<string, unsigned int>::iterator i = _map.find(name);
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (i != _map.end()) {
|
||||||
|
// remove variable from map
|
||||||
|
_map.erase(i->first);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
// TODO: remove unused stack entries
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool erase(const string& name)
|
void erase_all(void) {
|
||||||
{
|
// map
|
||||||
map<string, unsigned int>::iterator i = _map.find(name);
|
_map.erase(_map.begin(), _map.end());
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
if (i != _map.end())
|
|
||||||
{
|
|
||||||
// remove variable from map
|
|
||||||
_map.erase(i->first);
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
// TODO: remove unused stack entries
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase_all(void)
|
|
||||||
{
|
|
||||||
// map
|
|
||||||
_map.erase(_map.begin(), _map.end());
|
|
||||||
|
|
||||||
// and stack
|
// and stack
|
||||||
((stack*)this)->erase();
|
((stack*)this)->erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int count_vars() { return _map.size(); }
|
unsigned int count_vars() { return _map.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
map<string, unsigned int> _map;
|
map<string, unsigned int> _map;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __stack_h__
|
#endif // __stack_h__
|
||||||
|
|
|
@ -15,8 +15,9 @@ static const char description[] =
|
||||||
"using " ATTR_BOLD "GMP" ATTR_OFF " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n"
|
"using " ATTR_BOLD "GMP" ATTR_OFF " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n"
|
||||||
ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING " under GNU LGPL\n"
|
ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING " under GNU LGPL\n"
|
||||||
"and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n";
|
"and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n";
|
||||||
|
|
||||||
// syntax
|
// syntax
|
||||||
static const char syntax[] =
|
static const char syntax[] =
|
||||||
ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\n"
|
ATTR_BOLD "Syntax" ATTR_OFF
|
||||||
"with optional command = list of commands";
|
": rpn [command]\n"
|
||||||
|
"with optional command = list of commands";
|
||||||
|
|
Loading…
Reference in a new issue