mirror of
https://github.com/louisrubet/rpn
synced 2024-12-26 09:58:55 +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
|
||||
#define MPFR_DEFAULT_PREC_BITS 128
|
||||
|
||||
// 128 bits significand storing length in bytes, result of mpfr_custom_get_size(128)
|
||||
// 128 bits significand storing length in bytes, result of
|
||||
// mpfr_custom_get_size(128)
|
||||
#define MPFR_DEFAULT_STORING_LENGTH_BYTES 16
|
||||
|
||||
// constants
|
||||
|
@ -42,37 +43,46 @@
|
|||
#define MPFR_FORMAT_SCI "Re"
|
||||
#define MPFR_FORMAT_HEX "%Ra"
|
||||
|
||||
#define MPFR_RND_STRINGS { "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
|
||||
#define MPFR_RND_STRINGS \
|
||||
{ "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
|
||||
|
||||
// return values, used by all classes
|
||||
//
|
||||
typedef enum {
|
||||
ret_ok,
|
||||
ret_unknown_err,
|
||||
ret_missing_operand,
|
||||
ret_bad_operand_type,
|
||||
ret_out_of_range,
|
||||
ret_unknown_variable,
|
||||
ret_internal,
|
||||
ret_deadly,
|
||||
ret_good_bye,
|
||||
ret_not_impl,
|
||||
ret_nop,
|
||||
ret_syntax,
|
||||
ret_div_by_zero,
|
||||
ret_runtime_error,
|
||||
ret_abort_current_entry,
|
||||
ret_max
|
||||
ret_ok,
|
||||
ret_unknown_err,
|
||||
ret_missing_operand,
|
||||
ret_bad_operand_type,
|
||||
ret_out_of_range,
|
||||
ret_unknown_variable,
|
||||
ret_internal,
|
||||
ret_deadly,
|
||||
ret_good_bye,
|
||||
ret_not_impl,
|
||||
ret_nop,
|
||||
ret_syntax,
|
||||
ret_div_by_zero,
|
||||
ret_runtime_error,
|
||||
ret_abort_current_entry,
|
||||
ret_max
|
||||
} ret_value;
|
||||
|
||||
#define RET_VALUE_STRINGS { \
|
||||
"ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", \
|
||||
"deadly", "goodbye", "not implemented", "no operation", "syntax error", "division by zero", "runtime error", "aborted current entry" \
|
||||
}
|
||||
#define RET_VALUE_STRINGS \
|
||||
{ \
|
||||
"ok", "unknown command", "missing operand", "bad operand type", \
|
||||
"out of range", "unknown variable", "internal error, aborting", \
|
||||
"deadly", "goodbye", "not implemented", "no operation", \
|
||||
"syntax error", "division by zero", "runtime error", \
|
||||
"aborted current entry" \
|
||||
}
|
||||
|
||||
// command types
|
||||
//
|
||||
#define CMD_TYPE_STRINGS { "undef", "number", "complex", "string", "symbol", "program", "keyword", "keyword" }
|
||||
#define CMD_TYPE_STRINGS \
|
||||
{ \
|
||||
"undef", "number", "complex", "string", "symbol", "program", "keyword", \
|
||||
"keyword" \
|
||||
}
|
||||
|
||||
// history
|
||||
#define HISTORY_FILE ".rpn_history"
|
||||
|
@ -99,14 +109,14 @@ typedef enum {
|
|||
#error "Invalid MPFR Exp format"
|
||||
#endif
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(h,i) ((h) > (i) ? (h) : (i))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(h, i) ((h) > (i) ? (h) : (i))
|
||||
|
||||
#define MPFR_EXP_INF (MPFR_EXP_MIN+3)
|
||||
#define MPFR_EXP_NAN (MPFR_EXP_MIN+2)
|
||||
#define MPFR_EXP_INF (MPFR_EXP_MIN + 3)
|
||||
#define MPFR_EXP_NAN (MPFR_EXP_MIN + 2)
|
||||
#define MPFR_EXP(x) ((x)->_mpfr_exp)
|
||||
#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF)
|
||||
#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x),0))
|
||||
#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
||||
#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN)
|
||||
#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF)
|
||||
#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0)
|
||||
|
|
133
src/debug.h
133
src/debug.h
|
@ -2,97 +2,92 @@
|
|||
#define DEBUG_H
|
||||
|
||||
static void dump8(unsigned char* to_dump, unsigned long offset,
|
||||
unsigned long size)
|
||||
{
|
||||
const int block_size = 1;
|
||||
const int block_per_line = 16;
|
||||
int max_line = size / block_size;
|
||||
unsigned char mychar;
|
||||
int i;
|
||||
int j;
|
||||
for (i = 0; i < max_line; i++)
|
||||
{
|
||||
if ((i % block_per_line) == 0)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
printf(" ");
|
||||
for (j = i - block_per_line; j < i; j++)
|
||||
{
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127))
|
||||
mychar = '.';
|
||||
printf("%c", mychar);
|
||||
}
|
||||
}
|
||||
printf("\n%08lX:", offset + i * block_size);
|
||||
}
|
||||
printf(" %02hhX", *(to_dump + i));
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
unsigned long size) {
|
||||
const int block_size = 1;
|
||||
const int block_per_line = 16;
|
||||
int max_line = size / block_size;
|
||||
unsigned char mychar;
|
||||
int i;
|
||||
int j;
|
||||
for (i = 0; i < max_line; i++) {
|
||||
if ((i % block_per_line) == 0) {
|
||||
if (i > 0) {
|
||||
printf(" ");
|
||||
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++)
|
||||
{
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127))
|
||||
mychar = '.';
|
||||
printf("%c", mychar);
|
||||
for (j = i - block_per_line; j < i; j++) {
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127)) mychar = '.';
|
||||
printf("%c", mychar);
|
||||
}
|
||||
}
|
||||
printf("\n%08lX:", offset + i * block_size);
|
||||
}
|
||||
printf("\n");
|
||||
printf(" %02hhX", *(to_dump + i));
|
||||
}
|
||||
if (i > 0) {
|
||||
printf(" ");
|
||||
for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++) {
|
||||
mychar = *(to_dump + j);
|
||||
if ((mychar < 32) || (mychar >= 127)) mychar = '.';
|
||||
printf("%c", mychar);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//
|
||||
#define TRACE(...) do { printf(__VA_ARGS__); } while(0)
|
||||
#define TRACE(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
// chrono
|
||||
#include <time.h>
|
||||
|
||||
static int chrono_next = 0;
|
||||
static struct
|
||||
{
|
||||
struct timespec ts_point;
|
||||
char comment[256];
|
||||
static struct {
|
||||
struct timespec ts_point;
|
||||
char comment[256];
|
||||
} chrono_point[24];
|
||||
|
||||
static void chrono_start()
|
||||
{
|
||||
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
|
||||
strcpy(chrono_point[0].comment, "START");
|
||||
chrono_next = 1;
|
||||
static void chrono_start() {
|
||||
clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point);
|
||||
strcpy(chrono_point[0].comment, "START");
|
||||
chrono_next = 1;
|
||||
}
|
||||
|
||||
static void chrono_add(const char* comment)
|
||||
{
|
||||
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
|
||||
strcpy(chrono_point[chrono_next].comment, comment);
|
||||
chrono_next++;
|
||||
static void chrono_add(const char* comment) {
|
||||
clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point);
|
||||
strcpy(chrono_point[chrono_next].comment, comment);
|
||||
chrono_next++;
|
||||
}
|
||||
|
||||
static uint64_t chrono_diff_us(struct timespec* ts_from, struct timespec* ts_to)
|
||||
{
|
||||
uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL + ((uint64_t)ts_from->tv_nsec) / 1000UL;
|
||||
uint64_t to = (uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
|
||||
return to - from;
|
||||
static uint64_t chrono_diff_us(struct timespec* ts_from,
|
||||
struct timespec* ts_to) {
|
||||
uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL +
|
||||
((uint64_t)ts_from->tv_nsec) / 1000UL;
|
||||
uint64_t to =
|
||||
(uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL;
|
||||
return to - from;
|
||||
}
|
||||
|
||||
static void chrono_all_print(void)
|
||||
{
|
||||
for(int i = 1; i < chrono_next; i++)
|
||||
{
|
||||
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[i-1].ts_point, &chrono_point[i].ts_point), chrono_point[i].comment);
|
||||
}
|
||||
static void chrono_all_print(void) {
|
||||
for (int i = 1; i < chrono_next; i++) {
|
||||
printf("CHRONO [%lu us] %s\n",
|
||||
chrono_diff_us(&chrono_point[i - 1].ts_point,
|
||||
&chrono_point[i].ts_point),
|
||||
chrono_point[i].comment);
|
||||
}
|
||||
}
|
||||
|
||||
static void chrono_print(int chrono)
|
||||
{
|
||||
if (chrono >= 1)
|
||||
{
|
||||
printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[chrono-1].ts_point, &chrono_point[chrono].ts_point), chrono_point[chrono].comment);
|
||||
}
|
||||
static void chrono_print(int chrono) {
|
||||
if (chrono >= 1) {
|
||||
printf("CHRONO [%lu us] %s\n",
|
||||
chrono_diff_us(&chrono_point[chrono - 1].ts_point,
|
||||
&chrono_point[chrono].ts_point),
|
||||
chrono_point[chrono].comment);
|
||||
}
|
||||
}
|
||||
|
||||
#define max(a, b) (((a)>(b))?(a):(b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#endif
|
||||
|
|
234
src/main.cpp
234
src/main.cpp
|
@ -1,12 +1,12 @@
|
|||
// std c
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <linux/limits.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// internal includes
|
||||
#include "program.hpp"
|
||||
|
@ -16,149 +16,137 @@ static stack s_global_stack;
|
|||
static program* s_prog_to_interrupt = NULL;
|
||||
|
||||
// actions to be done at rpn exit
|
||||
void exit_interactive_rpn()
|
||||
{
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
if (pw != NULL)
|
||||
{
|
||||
char history_path[PATH_MAX];
|
||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||
void exit_interactive_rpn() {
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
if (pw != NULL) {
|
||||
char history_path[PATH_MAX];
|
||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||
|
||||
// trunc current history
|
||||
ofstream history(history_path, ios_base::out|ios_base::trunc);
|
||||
history.close();
|
||||
// trunc current history
|
||||
ofstream history(history_path, ios_base::out | ios_base::trunc);
|
||||
history.close();
|
||||
|
||||
// save it
|
||||
if (linenoiseHistorySave(history_path) != 0)
|
||||
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno));
|
||||
}
|
||||
// save it
|
||||
if (linenoiseHistorySave(history_path) != 0)
|
||||
fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n",
|
||||
history_path, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// actions to be done at rpn exit
|
||||
void init_interactive_rpn()
|
||||
{
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
if (pw != NULL)
|
||||
{
|
||||
char history_path[PATH_MAX];
|
||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||
void init_interactive_rpn() {
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
if (pw != NULL) {
|
||||
char history_path[PATH_MAX];
|
||||
sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE);
|
||||
|
||||
// don't care about errors
|
||||
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
|
||||
linenoiseHistoryLoad(history_path);
|
||||
}
|
||||
// don't care about errors
|
||||
linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES);
|
||||
linenoiseHistoryLoad(history_path);
|
||||
}
|
||||
}
|
||||
|
||||
// handle CtrlC signal
|
||||
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context)
|
||||
{
|
||||
if (s_prog_to_interrupt != NULL)
|
||||
{
|
||||
s_prog_to_interrupt->stop();
|
||||
s_prog_to_interrupt = NULL;
|
||||
}
|
||||
static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) {
|
||||
if (s_prog_to_interrupt != NULL) {
|
||||
s_prog_to_interrupt->stop();
|
||||
s_prog_to_interrupt = NULL;
|
||||
}
|
||||
|
||||
exit_interactive_rpn();
|
||||
exit_interactive_rpn();
|
||||
}
|
||||
|
||||
// handle SIGSEGV signal
|
||||
static void segv_handler(int sig, siginfo_t* siginfo, void* context)
|
||||
{
|
||||
fprintf(stderr, "Internal error\n");
|
||||
s_prog_to_interrupt->stop();
|
||||
s_prog_to_interrupt = NULL;
|
||||
static void segv_handler(int sig, siginfo_t* siginfo, void* context) {
|
||||
fprintf(stderr, "Internal error\n");
|
||||
s_prog_to_interrupt->stop();
|
||||
s_prog_to_interrupt = NULL;
|
||||
}
|
||||
|
||||
static void catch_signals(program* prog)
|
||||
{
|
||||
struct sigaction act;
|
||||
static void catch_signals(program* prog) {
|
||||
struct sigaction act;
|
||||
|
||||
s_prog_to_interrupt = prog;
|
||||
s_prog_to_interrupt = prog;
|
||||
|
||||
act.sa_sigaction = &ctrlc_handler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGINT, &act, NULL) < 0)
|
||||
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']", errno, strerror(errno));
|
||||
act.sa_sigaction = &ctrlc_handler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGINT, &act, NULL) < 0)
|
||||
(void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']",
|
||||
errno, strerror(errno));
|
||||
|
||||
act.sa_sigaction = &segv_handler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGSEGV, &act, NULL) < 0)
|
||||
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno));
|
||||
act.sa_sigaction = &segv_handler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGSEGV, &act, NULL) < 0)
|
||||
(void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
//
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
bool go_on = true;
|
||||
int main(int argc, char* argv[]) {
|
||||
int ret = 0;
|
||||
bool go_on = true;
|
||||
|
||||
// apply default configuration
|
||||
program::apply_default();
|
||||
// apply default configuration
|
||||
program::apply_default();
|
||||
|
||||
// run with interactive prompt
|
||||
if (argc == 1)
|
||||
{
|
||||
// init history
|
||||
init_interactive_rpn();
|
||||
// run with interactive prompt
|
||||
if (argc == 1) {
|
||||
// init history
|
||||
init_interactive_rpn();
|
||||
|
||||
// entry loop
|
||||
while(go_on)
|
||||
{
|
||||
// make program from interactive entry
|
||||
program prog;
|
||||
switch (program::entry(prog))
|
||||
{
|
||||
case ret_good_bye:
|
||||
go_on = false;
|
||||
break;
|
||||
case ret_abort_current_entry:
|
||||
break;
|
||||
default:
|
||||
// user could stop prog with CtrlC
|
||||
catch_signals(&prog);
|
||||
// entry loop
|
||||
while (go_on) {
|
||||
// make program from interactive entry
|
||||
program prog;
|
||||
switch (program::entry(prog)) {
|
||||
case ret_good_bye:
|
||||
go_on = false;
|
||||
break;
|
||||
case ret_abort_current_entry:
|
||||
break;
|
||||
default:
|
||||
// user could stop prog with CtrlC
|
||||
catch_signals(&prog);
|
||||
|
||||
// run it
|
||||
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
|
||||
go_on = false;
|
||||
else
|
||||
program::show_stack(s_global_stack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// manage history and exit
|
||||
exit_interactive_rpn();
|
||||
}
|
||||
// run with cmd line arguments
|
||||
else
|
||||
{
|
||||
program prog;
|
||||
string entry;
|
||||
int i;
|
||||
|
||||
// make one string from entry
|
||||
for (i=1; i<argc; i++)
|
||||
{
|
||||
entry += argv[i];
|
||||
entry += ' ';
|
||||
}
|
||||
|
||||
// make program
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
string separator = "";
|
||||
|
||||
// user could stop prog with CtrlC
|
||||
catch_signals(&prog);
|
||||
|
||||
// run it
|
||||
ret = prog.run(s_global_stack, s_global_heap);
|
||||
program::show_stack(s_global_stack, true);
|
||||
}
|
||||
// run it
|
||||
if (prog.run(s_global_stack, s_global_heap) == ret_good_bye)
|
||||
go_on = false;
|
||||
else
|
||||
program::show_stack(s_global_stack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_free_cache();
|
||||
// manage history and exit
|
||||
exit_interactive_rpn();
|
||||
}
|
||||
// run with cmd line arguments
|
||||
else {
|
||||
program prog;
|
||||
string entry;
|
||||
int i;
|
||||
|
||||
return ret;
|
||||
// make one string from entry
|
||||
for (i = 1; i < argc; i++) {
|
||||
entry += argv[i];
|
||||
entry += ' ';
|
||||
}
|
||||
|
||||
// make program
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok) {
|
||||
string separator = "";
|
||||
|
||||
// user could stop prog with CtrlC
|
||||
catch_signals(&prog);
|
||||
|
||||
// run it
|
||||
ret = prog.run(s_global_stack, s_global_heap);
|
||||
program::show_stack(s_global_stack, true);
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_free_cache();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
383
src/object.cpp
383
src/object.cpp
|
@ -1,9 +1,9 @@
|
|||
#include <string>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "mpfr.h"
|
||||
#include "constant.h"
|
||||
#include "mpfr.h"
|
||||
#include "object.hpp"
|
||||
|
||||
// floating_t statics
|
||||
|
@ -20,233 +20,198 @@ string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
|
|||
//
|
||||
const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
|
||||
|
||||
static bool is_min(mpfr_t p, mpfr_prec_t prec)
|
||||
{
|
||||
// see mpfr_vasprintf code
|
||||
bool ret;
|
||||
int round_away;
|
||||
switch (floating_t::s_mpfr_rnd)
|
||||
{
|
||||
case MPFR_RNDA:
|
||||
round_away = 1;
|
||||
break;
|
||||
case MPFR_RNDD:
|
||||
round_away = MPFR_IS_NEG (p);
|
||||
break;
|
||||
case MPFR_RNDU:
|
||||
round_away = MPFR_IS_POS (p);
|
||||
break;
|
||||
case MPFR_RNDN:
|
||||
{
|
||||
/* compare |p| to y = 0.5*10^(-prec) */
|
||||
mpfr_t y;
|
||||
mpfr_exp_t e = MAX (MPFR_PREC (p), 56);
|
||||
mpfr_init2 (y, e + 8);
|
||||
do
|
||||
{
|
||||
/* find a lower approximation of
|
||||
0.5*10^(-prec) different from |p| */
|
||||
e += 8;
|
||||
mpfr_set_prec (y, e);
|
||||
mpfr_set_si (y, -prec, MPFR_RNDN);
|
||||
mpfr_exp10 (y, y, MPFR_RNDD);
|
||||
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
|
||||
} while (mpfr_cmpabs (y, p) == 0);
|
||||
static bool is_min(mpfr_t p, mpfr_prec_t prec) {
|
||||
// see mpfr_vasprintf code
|
||||
bool ret;
|
||||
int round_away;
|
||||
switch (floating_t::s_mpfr_rnd) {
|
||||
case MPFR_RNDA:
|
||||
round_away = 1;
|
||||
break;
|
||||
case MPFR_RNDD:
|
||||
round_away = MPFR_IS_NEG(p);
|
||||
break;
|
||||
case MPFR_RNDU:
|
||||
round_away = MPFR_IS_POS(p);
|
||||
break;
|
||||
case MPFR_RNDN: {
|
||||
/* compare |p| to y = 0.5*10^(-prec) */
|
||||
mpfr_t y;
|
||||
mpfr_exp_t e = MAX(MPFR_PREC(p), 56);
|
||||
mpfr_init2(y, e + 8);
|
||||
do {
|
||||
/* find a lower approximation of
|
||||
0.5*10^(-prec) different from |p| */
|
||||
e += 8;
|
||||
mpfr_set_prec(y, e);
|
||||
mpfr_set_si(y, -prec, MPFR_RNDN);
|
||||
mpfr_exp10(y, y, MPFR_RNDD);
|
||||
mpfr_div_2ui(y, y, 1, MPFR_RNDN);
|
||||
} while (mpfr_cmpabs(y, p) == 0);
|
||||
|
||||
round_away = mpfr_cmpabs (y, p) < 0;
|
||||
mpfr_clear (y);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
round_away = 0;
|
||||
}
|
||||
round_away = mpfr_cmpabs(y, p) < 0;
|
||||
mpfr_clear(y);
|
||||
} break;
|
||||
default:
|
||||
round_away = 0;
|
||||
}
|
||||
|
||||
if (round_away)
|
||||
/* round away from zero: the last output digit is '1' */
|
||||
ret = true;
|
||||
else
|
||||
/* only zeros in fractional part */
|
||||
ret = false;
|
||||
return ret;
|
||||
if (round_away) /* round away from zero: the last output digit is '1' */
|
||||
ret = true;
|
||||
else
|
||||
/* only zeros in fractional part */
|
||||
ret = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL)
|
||||
{
|
||||
// see mpfr_vasprintf code
|
||||
mpfr_exp_t exp = mpfr_get_exp(real);
|
||||
int digits = 0; //forced 0 digits after separator
|
||||
int i;
|
||||
static void print_fix(FILE* stream, mpfr_t real, int base,
|
||||
const char* write_after_sign = NULL) {
|
||||
// see mpfr_vasprintf code
|
||||
mpfr_exp_t exp = mpfr_get_exp(real);
|
||||
int digits = 0; // forced 0 digits after separator
|
||||
int i;
|
||||
|
||||
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real)))
|
||||
{
|
||||
if (MPFR_IS_NAN(real))
|
||||
fputs("nan", stream);
|
||||
else if (MPFR_IS_INF(real))
|
||||
{
|
||||
if (MPFR_IS_NEG(real))
|
||||
fputc('-', stream);
|
||||
fputs("inf", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
// zero
|
||||
if (MPFR_IS_NEG(real))
|
||||
fputc('-', stream);//signed zero is allowed
|
||||
if (write_after_sign != NULL)
|
||||
fputs(write_after_sign, stream);
|
||||
fputc('0', stream);
|
||||
if (digits > 0)
|
||||
{
|
||||
fputc('.', stream);
|
||||
for(i = 0; i < digits; i++)
|
||||
fputc('0', stream);
|
||||
}
|
||||
}
|
||||
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) {
|
||||
if (MPFR_IS_NAN(real))
|
||||
fputs("nan", stream);
|
||||
else if (MPFR_IS_INF(real)) {
|
||||
if (MPFR_IS_NEG(real)) fputc('-', stream);
|
||||
fputs("inf", stream);
|
||||
} else {
|
||||
// zero
|
||||
if (MPFR_IS_NEG(real)) fputc('-', stream); // signed zero is allowed
|
||||
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||
fputc('0', stream);
|
||||
if (digits > 0) {
|
||||
fputc('.', stream);
|
||||
for (i = 0; i < digits; i++) fputc('0', stream);
|
||||
}
|
||||
}
|
||||
else if (exp < -digits)
|
||||
{
|
||||
if (MPFR_IS_NEG(real))
|
||||
fputc('-', stream);
|
||||
if (write_after_sign != NULL)
|
||||
fputs(write_after_sign, stream);
|
||||
} else if (exp < -digits) {
|
||||
if (MPFR_IS_NEG(real)) fputc('-', stream);
|
||||
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||
fputc('0', stream);
|
||||
if (digits > 0) {
|
||||
fputc('.', stream);
|
||||
for (i = 0; i < digits - 1; i++) fputc('0', stream);
|
||||
|
||||
if (is_min(real, digits))
|
||||
fputc('1', stream);
|
||||
else
|
||||
fputc('0', stream);
|
||||
if (digits > 0)
|
||||
{
|
||||
}
|
||||
} else {
|
||||
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real,
|
||||
floating_t::s_mpfr_rnd);
|
||||
char* print_from;
|
||||
if (str != NULL) {
|
||||
int len = strlen(str);
|
||||
print_from = str;
|
||||
if (len > 0) {
|
||||
if (print_from[0] == '-') {
|
||||
fputc(print_from[0], stream);
|
||||
len--;
|
||||
print_from++;
|
||||
} else if (print_from[0] == '+') {
|
||||
len--;
|
||||
print_from++;
|
||||
}
|
||||
if (write_after_sign != NULL) fputs(write_after_sign, stream);
|
||||
if (exp < 0) {
|
||||
fputc('0', stream);
|
||||
if (digits > 0) {
|
||||
fputc('.', stream);
|
||||
for (i = 0; i < -(int)exp; i++) fputc('0', stream);
|
||||
fputs(str, stream);
|
||||
for (i = 0; i < (int)(digits - len + exp); i++) fputc('0', stream);
|
||||
}
|
||||
} else {
|
||||
if (exp == 0)
|
||||
fputc('0', stream);
|
||||
else
|
||||
for (i = 0; i < (int)exp; i++) fputc(print_from[i], stream);
|
||||
if (digits > 0) {
|
||||
fputc('.', stream);
|
||||
for (i = 0; i< digits - 1; i++)
|
||||
fputc('0', stream);
|
||||
|
||||
if (is_min(real, digits))
|
||||
fputc('1', stream);
|
||||
else
|
||||
fputc('0', stream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, floating_t::s_mpfr_rnd);
|
||||
char* print_from;
|
||||
if(str != NULL)
|
||||
{
|
||||
int len = strlen(str);
|
||||
print_from = str;
|
||||
if (len > 0)
|
||||
{
|
||||
if (print_from[0] == '-')
|
||||
{
|
||||
fputc(print_from[0], stream);
|
||||
len--;
|
||||
print_from++;
|
||||
}
|
||||
else if (print_from[0] == '+')
|
||||
{
|
||||
len--;
|
||||
print_from++;
|
||||
}
|
||||
if (write_after_sign != NULL)
|
||||
fputs(write_after_sign, stream);
|
||||
if (exp < 0)
|
||||
{
|
||||
fputc('0', stream);
|
||||
if (digits > 0)
|
||||
{
|
||||
fputc('.', stream);
|
||||
for (i = 0; i < -(int)exp; i++)
|
||||
fputc('0', stream);
|
||||
fputs(str, stream);
|
||||
for (i = 0; i < (int)(digits - len + exp); i++)
|
||||
fputc('0', stream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exp == 0)
|
||||
fputc('0', stream);
|
||||
else
|
||||
for (i = 0; i < (int)exp; i++)
|
||||
fputc(print_from[i], stream);
|
||||
if (digits > 0)
|
||||
{
|
||||
fputc('.', stream);
|
||||
|
||||
int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
|
||||
for (i = (int)exp; i < remaining + (int)exp; i++)
|
||||
fputc(print_from[i], stream);
|
||||
for (i = 0; i < (int)(exp + digits - len); i++)
|
||||
fputc('0', stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
mpfr_free_str(str);
|
||||
int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1;
|
||||
for (i = (int)exp; i < remaining + (int)exp; i++)
|
||||
fputc(print_from[i], stream);
|
||||
for (i = 0; i < (int)(exp + digits - len); i++) fputc('0', stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
mpfr_free_str(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void object::show(FILE* stream)
|
||||
{
|
||||
int digits;
|
||||
char* str;
|
||||
char base[32];
|
||||
void object::show(FILE* stream) {
|
||||
int digits;
|
||||
char* str;
|
||||
char base[32];
|
||||
|
||||
switch(_type)
|
||||
{
|
||||
switch (_type) {
|
||||
case cmd_number:
|
||||
switch(((number*)this)->_representation)
|
||||
{
|
||||
case number::dec:
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr);
|
||||
break;
|
||||
case number::hex:
|
||||
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
|
||||
break;
|
||||
case number::bin:
|
||||
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
|
||||
break;
|
||||
case number::base:
|
||||
sprintf(base, "%db", ((number*)this)->_base);
|
||||
print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base, base);
|
||||
break;
|
||||
default:
|
||||
fprintf(stream, "<unknown number representation>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
switch (((number*)this)->_representation) {
|
||||
case number::dec:
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||
((number*)this)->_value.mpfr);
|
||||
break;
|
||||
case number::hex:
|
||||
print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x");
|
||||
break;
|
||||
case number::bin:
|
||||
print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b");
|
||||
break;
|
||||
case number::base:
|
||||
sprintf(base, "%db", ((number*)this)->_base);
|
||||
print_fix(stream, ((number*)this)->_value.mpfr,
|
||||
((number*)this)->_base, base);
|
||||
break;
|
||||
default:
|
||||
fprintf(stream, "<unknown number representation>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case cmd_complex:
|
||||
switch(((complex*)this)->_representation)
|
||||
{
|
||||
case number::dec:
|
||||
fprintf(stream, "(");
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr);
|
||||
fprintf(stream, ",");
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->im()->mpfr);
|
||||
fprintf(stream, ")");
|
||||
break;
|
||||
case number::hex:
|
||||
fprintf(stream, "(");
|
||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->re()->mpfr);
|
||||
fprintf(stream, ",");
|
||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->im()->mpfr);
|
||||
fprintf(stream, ")");
|
||||
break;
|
||||
default:
|
||||
fprintf(stream, "<unknown complex representation>");
|
||||
}
|
||||
break;
|
||||
switch (((complex*)this)->_representation) {
|
||||
case number::dec:
|
||||
fprintf(stream, "(");
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||
((complex*)this)->re()->mpfr);
|
||||
fprintf(stream, ",");
|
||||
mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(),
|
||||
((complex*)this)->im()->mpfr);
|
||||
fprintf(stream, ")");
|
||||
break;
|
||||
case number::hex:
|
||||
fprintf(stream, "(");
|
||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
|
||||
((complex*)this)->re()->mpfr);
|
||||
fprintf(stream, ",");
|
||||
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(),
|
||||
((complex*)this)->im()->mpfr);
|
||||
fprintf(stream, ")");
|
||||
break;
|
||||
default:
|
||||
fprintf(stream, "<unknown complex representation>");
|
||||
}
|
||||
break;
|
||||
case cmd_string:
|
||||
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
|
||||
break;
|
||||
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
|
||||
break;
|
||||
case cmd_program:
|
||||
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
|
||||
break;
|
||||
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
|
||||
break;
|
||||
case cmd_symbol:
|
||||
fprintf(stream, "'%s'", ((symbol*)this)->_value);
|
||||
break;
|
||||
fprintf(stream, "'%s'", ((symbol*)this)->_value);
|
||||
break;
|
||||
case cmd_keyword:
|
||||
case cmd_branch:
|
||||
fprintf(stream, "%s", ((keyword*)this)->_value);
|
||||
break;
|
||||
fprintf(stream, "%s", ((keyword*)this)->_value);
|
||||
break;
|
||||
default:
|
||||
fprintf(stream, "< unknown object representation >");
|
||||
break;
|
||||
}
|
||||
fprintf(stream, "< unknown object representation >");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
482
src/object.hpp
482
src/object.hpp
|
@ -7,15 +7,15 @@
|
|||
// definitions for objects
|
||||
////
|
||||
typedef enum {
|
||||
cmd_undef,
|
||||
cmd_number,// floating point number
|
||||
cmd_complex,// complex, couple of floating point numbers
|
||||
cmd_string,// string like "string"
|
||||
cmd_symbol,// symbol like 'symbol'
|
||||
cmd_program,// program like << instructions >>
|
||||
cmd_keyword,// langage keyword
|
||||
cmd_branch,// langage branch keyword
|
||||
cmd_max
|
||||
cmd_undef,
|
||||
cmd_number, // floating point number
|
||||
cmd_complex, // complex, couple of floating point numbers
|
||||
cmd_string, // string like "string"
|
||||
cmd_symbol, // symbol like 'symbol'
|
||||
cmd_program, // program like << instructions >>
|
||||
cmd_keyword, // langage keyword
|
||||
cmd_branch, // langage branch keyword
|
||||
cmd_max
|
||||
} cmd_type_t;
|
||||
|
||||
class program;
|
||||
|
@ -26,330 +26,262 @@ typedef int (program::*branch_fn_t)(branch&);
|
|||
|
||||
// MPFR object
|
||||
////
|
||||
struct floating_t
|
||||
{
|
||||
mpfr_prec_t mpfr_prec;// precision in bits
|
||||
unsigned int mpfr_prec_bytes;// significand storing length in bytes
|
||||
mpfr_t mpfr;//mpfr object
|
||||
struct floating_t {
|
||||
mpfr_prec_t mpfr_prec; // precision in bits
|
||||
unsigned int mpfr_prec_bytes; // significand storing length in bytes
|
||||
mpfr_t mpfr; // mpfr object
|
||||
|
||||
void init()
|
||||
{
|
||||
void* significand = (void*)(this+1);
|
||||
mpfr_prec = s_mpfr_prec;
|
||||
mpfr_prec_bytes = s_mpfr_prec_bytes;
|
||||
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
|
||||
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
|
||||
}
|
||||
void init() {
|
||||
void* significand = (void*)(this + 1);
|
||||
mpfr_prec = s_mpfr_prec;
|
||||
mpfr_prec_bytes = s_mpfr_prec_bytes;
|
||||
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
|
||||
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand);
|
||||
}
|
||||
|
||||
void move()
|
||||
{
|
||||
void* significand = (void*)(this+1);
|
||||
mpfr_custom_move(mpfr, significand);
|
||||
}
|
||||
void move() {
|
||||
void* significand = (void*)(this + 1);
|
||||
mpfr_custom_move(mpfr, significand);
|
||||
}
|
||||
|
||||
floating_t& operator=(const double val)
|
||||
{
|
||||
mpfr_set_d(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); }
|
||||
|
||||
floating_t& operator=(const long int val)
|
||||
{
|
||||
mpfr_set_si(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
floating_t& operator=(const long int val) {
|
||||
mpfr_set_si(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
|
||||
floating_t& operator=(const unsigned long val)
|
||||
{
|
||||
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
floating_t& operator=(const unsigned long val) {
|
||||
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
|
||||
}
|
||||
|
||||
operator double()
|
||||
{
|
||||
return mpfr_get_d(mpfr, s_mpfr_rnd);
|
||||
}
|
||||
operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); }
|
||||
|
||||
operator int()
|
||||
{
|
||||
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
|
||||
}
|
||||
|
||||
operator long()
|
||||
{
|
||||
return mpfr_get_si(mpfr, s_mpfr_rnd);
|
||||
}
|
||||
operator int() { return (int)mpfr_get_si(mpfr, s_mpfr_rnd); }
|
||||
|
||||
bool operator>(const floating_t right)
|
||||
{
|
||||
return mpfr_cmp(mpfr, right.mpfr) > 0;
|
||||
}
|
||||
operator long() { return mpfr_get_si(mpfr, s_mpfr_rnd); }
|
||||
|
||||
bool operator<(const floating_t right)
|
||||
{
|
||||
return mpfr_cmp(mpfr, right.mpfr) < 0;
|
||||
}
|
||||
bool operator>(const floating_t right) {
|
||||
return mpfr_cmp(mpfr, right.mpfr) > 0;
|
||||
}
|
||||
|
||||
// default precision in bits, precision length in bytes, rounding mode
|
||||
static mpfr_prec_t s_mpfr_prec;
|
||||
static unsigned int s_mpfr_prec_bytes;
|
||||
static mpfr_rnd_t s_mpfr_rnd;
|
||||
static const char* s_mpfr_rnd_str[5];
|
||||
bool operator<(const floating_t right) {
|
||||
return mpfr_cmp(mpfr, right.mpfr) < 0;
|
||||
}
|
||||
|
||||
// default precision in bits, precision length in bytes, rounding mode
|
||||
static mpfr_prec_t s_mpfr_prec;
|
||||
static unsigned int s_mpfr_prec_bytes;
|
||||
static mpfr_rnd_t s_mpfr_rnd;
|
||||
static const char* s_mpfr_rnd_str[5];
|
||||
};
|
||||
|
||||
// object - a generic stack object
|
||||
////
|
||||
struct object
|
||||
{
|
||||
// object type
|
||||
cmd_type_t _type;
|
||||
unsigned int _size;
|
||||
struct object {
|
||||
// object type
|
||||
cmd_type_t _type;
|
||||
unsigned int _size;
|
||||
|
||||
//
|
||||
unsigned int size() { return _size; }
|
||||
//
|
||||
unsigned int size() { return _size; }
|
||||
|
||||
void show(FILE* stream = stdout);
|
||||
void show(FILE* stream = stdout);
|
||||
|
||||
//
|
||||
static const char* s_cmd_type_string[cmd_max];
|
||||
//
|
||||
static const char* s_cmd_type_string[cmd_max];
|
||||
};
|
||||
|
||||
// stack objects derived from object
|
||||
////
|
||||
struct number : public object
|
||||
{
|
||||
// members
|
||||
enum {
|
||||
dec,
|
||||
hex,
|
||||
bin,
|
||||
base
|
||||
} _representation;
|
||||
// base
|
||||
// carefull: _base is used only if _representation = base
|
||||
int _base;
|
||||
// mind that float value is at the end of the object
|
||||
// because its mantissa is just after the obj in memory
|
||||
floating_t _value;
|
||||
struct number : public object {
|
||||
// members
|
||||
enum { dec, hex, bin, base } _representation;
|
||||
// base
|
||||
// carefull: _base is used only if _representation = base
|
||||
int _base;
|
||||
// mind that float value is at the end of the object
|
||||
// because its mantissa is just after the obj in memory
|
||||
floating_t _value;
|
||||
|
||||
// publics
|
||||
number() { _type = cmd_number; }
|
||||
// publics
|
||||
number() { _type = cmd_number; }
|
||||
|
||||
void init()
|
||||
{
|
||||
_type = cmd_number;
|
||||
_representation = dec;
|
||||
_value.init();
|
||||
}
|
||||
void init() {
|
||||
_type = cmd_number;
|
||||
_representation = dec;
|
||||
_value.init();
|
||||
}
|
||||
|
||||
void move()
|
||||
{
|
||||
_value.move();
|
||||
}
|
||||
void move() { _value.move(); }
|
||||
|
||||
void set(unsigned long value)
|
||||
{
|
||||
_type = cmd_number;
|
||||
_value = value;
|
||||
}
|
||||
void set(unsigned long value) {
|
||||
_type = cmd_number;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
static unsigned int calc_size()
|
||||
{
|
||||
return (unsigned int)(sizeof(number)+floating_t::s_mpfr_prec_bytes);
|
||||
}
|
||||
static unsigned int calc_size() {
|
||||
return (unsigned int)(sizeof(number) + floating_t::s_mpfr_prec_bytes);
|
||||
}
|
||||
|
||||
// representation mode
|
||||
typedef enum {
|
||||
std,
|
||||
fix,
|
||||
sci
|
||||
} mode_enum;
|
||||
static mode_enum s_mode;
|
||||
// representation mode
|
||||
typedef enum { std, fix, sci } mode_enum;
|
||||
static mode_enum s_mode;
|
||||
|
||||
// precision
|
||||
static int s_decimal_digits;
|
||||
static string s_mpfr_printf_format;
|
||||
// precision
|
||||
static int s_decimal_digits;
|
||||
static string s_mpfr_printf_format;
|
||||
};
|
||||
|
||||
// stack objects derived from object
|
||||
////
|
||||
struct complex : public object
|
||||
{
|
||||
enum {
|
||||
dec,
|
||||
hex
|
||||
} _representation;
|
||||
// mind that re float value is at the end of the object
|
||||
// because its mantissa is just after the obj in memory
|
||||
floating_t _re;
|
||||
struct complex : public object {
|
||||
enum { dec, hex } _representation;
|
||||
// mind that re float value is at the end of the object
|
||||
// because its mantissa is just after the obj in memory
|
||||
floating_t _re;
|
||||
|
||||
complex() { _type = cmd_complex; }
|
||||
complex() { _type = cmd_complex; }
|
||||
|
||||
// re and im float values are at the end of the object
|
||||
floating_t* re() { return &_re; }
|
||||
floating_t* im() { return (floating_t*)((char*)&_re + sizeof(floating_t) + _re.mpfr_prec_bytes); }
|
||||
// re and im float values are at the end of the object
|
||||
floating_t* re() { return &_re; }
|
||||
floating_t* im() {
|
||||
return (floating_t*)((char*)&_re + sizeof(floating_t) +
|
||||
_re.mpfr_prec_bytes);
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
_type = cmd_complex;
|
||||
_representation = dec;
|
||||
re()->init();
|
||||
im()->init();
|
||||
}
|
||||
void init() {
|
||||
_type = cmd_complex;
|
||||
_representation = dec;
|
||||
re()->init();
|
||||
im()->init();
|
||||
}
|
||||
|
||||
void move()
|
||||
{
|
||||
re()->move();
|
||||
im()->move();
|
||||
}
|
||||
void move() {
|
||||
re()->move();
|
||||
im()->move();
|
||||
}
|
||||
|
||||
static unsigned int calc_size()
|
||||
{
|
||||
return (unsigned int)(sizeof(complex)+2*(sizeof(floating_t)+floating_t::s_mpfr_prec_bytes));
|
||||
}
|
||||
static unsigned int calc_size() {
|
||||
return (
|
||||
unsigned int)(sizeof(complex) +
|
||||
2 * (sizeof(floating_t) + floating_t::s_mpfr_prec_bytes));
|
||||
}
|
||||
};
|
||||
|
||||
struct ostring : public object
|
||||
{
|
||||
// ostring may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_string;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value[_len] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
struct ostring : public object {
|
||||
// ostring may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len) {
|
||||
_type = cmd_string;
|
||||
if (value != NULL) {
|
||||
if (len > 0) (void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
} else {
|
||||
_value[_len] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// length of _value, not including the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
// length of _value, not including the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
struct oprogram : public object
|
||||
{
|
||||
// oprogram may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_program;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
struct oprogram : public object {
|
||||
// oprogram may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len) {
|
||||
_type = cmd_program;
|
||||
if (value != NULL) {
|
||||
if (len > 0) (void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
} else {
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
struct symbol : public object
|
||||
{
|
||||
// symbol may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len, bool auto_eval)
|
||||
{
|
||||
_type = cmd_symbol;
|
||||
_auto_eval = auto_eval;
|
||||
struct symbol : public object {
|
||||
// symbol may first have been allocated with len+1 bytes
|
||||
void set(const char* value, unsigned int len, bool auto_eval) {
|
||||
_type = cmd_symbol;
|
||||
_auto_eval = auto_eval;
|
||||
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
if (value != NULL) {
|
||||
if (len > 0) (void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
} else {
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool _auto_eval;
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
//
|
||||
bool _auto_eval;
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
struct keyword : public object
|
||||
{
|
||||
// keyword may first have been allocated with len+1 bytes
|
||||
void set(program_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_keyword;
|
||||
_fn = fn;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
struct keyword : public object {
|
||||
// keyword may first have been allocated with len+1 bytes
|
||||
void set(program_fn_t fn, const char* value, unsigned int len) {
|
||||
_type = cmd_keyword;
|
||||
_fn = fn;
|
||||
if (value != NULL) {
|
||||
if (len > 0) (void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
} else {
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
program_fn_t _fn;
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
//
|
||||
program_fn_t _fn;
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
struct branch : public object
|
||||
{
|
||||
//
|
||||
void set(branch_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
arg1 = -1;
|
||||
arg2 = -1;
|
||||
arg3 = -1;
|
||||
farg1 = NULL;
|
||||
farg2 = NULL;
|
||||
arg_bool = 0;
|
||||
if (value != NULL)
|
||||
{
|
||||
if (len>0)
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
struct branch : public object {
|
||||
//
|
||||
void set(branch_fn_t fn, const char* value, unsigned int len) {
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
arg1 = -1;
|
||||
arg2 = -1;
|
||||
arg3 = -1;
|
||||
farg1 = NULL;
|
||||
farg2 = NULL;
|
||||
arg_bool = 0;
|
||||
if (value != NULL) {
|
||||
if (len > 0) (void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
} else {
|
||||
_value[0] = 0;
|
||||
_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
number *farg1, *farg2;
|
||||
bool arg_bool;
|
||||
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
number *farg1, *farg2;
|
||||
bool arg_bool;
|
||||
|
||||
// length of _value, not includiong the terminal '\0'
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
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;
|
||||
|
||||
//
|
||||
program::keyword_t program::s_keywords[] =
|
||||
{
|
||||
//GENERAL
|
||||
{ cmd_undef, "", NULL, "\nGENERAL"},
|
||||
{ cmd_keyword, "nop", &program::rpn_nop, "no operation"},
|
||||
{ cmd_keyword, "help", &program::rpn_help, "this help message" },
|
||||
{ cmd_keyword, "h", &program::rpn_help, "" },
|
||||
{ cmd_keyword, "?", &program::rpn_help, "" },
|
||||
{ cmd_keyword, "quit", &program::rpn_good_bye, "quit software" },
|
||||
{ cmd_keyword, "q", &program::rpn_good_bye, "" },
|
||||
{ cmd_keyword, "exit", &program::rpn_good_bye, "" },
|
||||
{ cmd_keyword, "test", &program::rpn_test, "" }, //not seen by user
|
||||
{ cmd_keyword, "version", &program::rpn_version, "show rpn version" },
|
||||
{ cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string" },
|
||||
{ cmd_keyword, "history", &program::rpn_history, "see commands history" },
|
||||
program::keyword_t program::s_keywords[] = {
|
||||
// GENERAL
|
||||
{cmd_undef, "", NULL, "\nGENERAL"},
|
||||
{cmd_keyword, "nop", &program::rpn_nop, "no operation"},
|
||||
{cmd_keyword, "help", &program::rpn_help, "this help message"},
|
||||
{cmd_keyword, "h", &program::rpn_help, ""},
|
||||
{cmd_keyword, "?", &program::rpn_help, ""},
|
||||
{cmd_keyword, "quit", &program::rpn_good_bye, "quit software"},
|
||||
{cmd_keyword, "q", &program::rpn_good_bye, ""},
|
||||
{cmd_keyword, "exit", &program::rpn_good_bye, ""},
|
||||
{cmd_keyword, "test", &program::rpn_test, ""}, // not seen by user
|
||||
{cmd_keyword, "version", &program::rpn_version, "show rpn version"},
|
||||
{cmd_keyword, "uname", &program::rpn_uname,
|
||||
"show rpn complete identification string"},
|
||||
{cmd_keyword, "history", &program::rpn_history, "see commands history"},
|
||||
|
||||
//USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||
{ cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||
{ cmd_keyword, "+", &program::rpn_plus, "addition" },
|
||||
{ cmd_keyword, "-", &program::rpn_minus, "substraction" },
|
||||
{ cmd_keyword, "chs", &program::rpn_neg , "negation" },
|
||||
{ cmd_keyword, "neg", &program::rpn_neg , "" },
|
||||
{ cmd_keyword, "*", &program::rpn_mul, "multiplication" },
|
||||
{ cmd_keyword, "/", &program::rpn_div, "division" },
|
||||
{ cmd_keyword, "inv", &program::rpn_inv, "inverse" },
|
||||
{ cmd_keyword, "^", &program::rpn_power, "power" },
|
||||
{ cmd_keyword, "pow", &program::rpn_power, "" },
|
||||
{ cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root" },
|
||||
{ cmd_keyword, "sq", &program::rpn_square, "rpn_square" },
|
||||
{ cmd_keyword, "sqr", &program::rpn_square, "" },
|
||||
{ cmd_keyword, "abs", &program::rpn_abs, "absolute value" },
|
||||
{ cmd_keyword, "dec", &program::rpn_dec, "decimal representation" },
|
||||
{ cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation" },
|
||||
{ cmd_keyword, "bin", &program::rpn_bin, "decimal representation" },
|
||||
{ cmd_keyword, "base", &program::rpn_base, "arbitrary base representation" },
|
||||
{ cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0" },
|
||||
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||
{cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||
{cmd_keyword, "+", &program::rpn_plus, "addition"},
|
||||
{cmd_keyword, "-", &program::rpn_minus, "substraction"},
|
||||
{cmd_keyword, "chs", &program::rpn_neg, "negation"},
|
||||
{cmd_keyword, "neg", &program::rpn_neg, ""},
|
||||
{cmd_keyword, "*", &program::rpn_mul, "multiplication"},
|
||||
{cmd_keyword, "/", &program::rpn_div, "division"},
|
||||
{cmd_keyword, "inv", &program::rpn_inv, "inverse"},
|
||||
{cmd_keyword, "^", &program::rpn_power, "power"},
|
||||
{cmd_keyword, "pow", &program::rpn_power, ""},
|
||||
{cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
|
||||
{cmd_keyword, "sq", &program::rpn_square, "rpn_square"},
|
||||
{cmd_keyword, "sqr", &program::rpn_square, ""},
|
||||
{cmd_keyword, "abs", &program::rpn_abs, "absolute value"},
|
||||
{cmd_keyword, "dec", &program::rpn_dec, "decimal representation"},
|
||||
{cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"},
|
||||
{cmd_keyword, "bin", &program::rpn_bin, "decimal representation"},
|
||||
{cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"},
|
||||
{cmd_keyword, "sign", &program::rpn_sign,
|
||||
"1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"},
|
||||
|
||||
//OPERATIONS ON REALS
|
||||
{ cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
|
||||
{ cmd_keyword, "%", &program::rpn_purcent, "purcent" },
|
||||
{ cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent" },
|
||||
{ cmd_keyword, "mod", &program::rpn_modulo, "modulo" },
|
||||
{ cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x" },
|
||||
{ cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number" },
|
||||
{ cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number" },
|
||||
{ cmd_keyword, "floor", &program::rpn_floor, "largest number <=" },
|
||||
{ cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >=" },
|
||||
{ cmd_keyword, "ip", &program::rpn_ip, "integer part" },
|
||||
{ cmd_keyword, "fp", &program::rpn_fp, "fractional part" },
|
||||
{ cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers" },
|
||||
{ cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers" },
|
||||
// OPERATIONS ON REALS
|
||||
{cmd_undef, "", NULL, "\nOPERATIONS ON REALS"},
|
||||
{cmd_keyword, "%", &program::rpn_purcent, "purcent"},
|
||||
{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
|
||||
{cmd_keyword, "mod", &program::rpn_modulo, "modulo"},
|
||||
{cmd_keyword, "fact", &program::rpn_fact,
|
||||
"n! for integer n or Gamma(x+1) for fractional x"},
|
||||
{cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"},
|
||||
{cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
|
||||
{cmd_keyword, "floor", &program::rpn_floor, "largest number <="},
|
||||
{cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="},
|
||||
{cmd_keyword, "ip", &program::rpn_ip, "integer part"},
|
||||
{cmd_keyword, "fp", &program::rpn_fp, "fractional part"},
|
||||
{cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"},
|
||||
{cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"},
|
||||
|
||||
//nOPERATIONS ON COMPLEXES
|
||||
{ cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
|
||||
{ cmd_keyword, "re", &program::rpn_re, "complex real part" },
|
||||
{ cmd_keyword, "im", &program::rpn_im, "complex imaginary part" },
|
||||
{ cmd_keyword, "conj", &program::rpn_conj, "complex conjugate" },
|
||||
{ cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians" },
|
||||
{ cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals" },
|
||||
{ cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex" },
|
||||
{ cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar" },
|
||||
{ cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian" },
|
||||
// nOPERATIONS ON COMPLEXES
|
||||
{cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"},
|
||||
{cmd_keyword, "re", &program::rpn_re, "complex real part"},
|
||||
{cmd_keyword, "im", &program::rpn_im, "complex imaginary part"},
|
||||
{cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"},
|
||||
{cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"},
|
||||
{cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"},
|
||||
{cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
|
||||
{cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
|
||||
{cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
|
||||
|
||||
//MODE
|
||||
{ cmd_undef, "", NULL, "\nMODE"},
|
||||
{ cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std" },
|
||||
{ cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix" },
|
||||
{ cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci" },
|
||||
{ cmd_keyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec" },
|
||||
{ cmd_keyword, "round", &program::rpn_round, "set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward +inf\", \"toward -inf\", \"away from zero\"] round" },
|
||||
{ cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default" },
|
||||
{ cmd_keyword, "type", &program::rpn_type, "show type of stack first entry" },
|
||||
// MODE
|
||||
{cmd_undef, "", NULL, "\nMODE"},
|
||||
{cmd_keyword, "std", &program::rpn_std,
|
||||
"standard floating numbers representation. ex: std"},
|
||||
{cmd_keyword, "fix", &program::rpn_fix,
|
||||
"fixed point representation. ex: 6 fix"},
|
||||
{cmd_keyword, "sci", &program::rpn_sci,
|
||||
"scientific floating point representation. ex: 20 sci"},
|
||||
{cmd_keyword, "prec", &program::rpn_precision,
|
||||
"set float precision in bits. ex: 256 prec"},
|
||||
{cmd_keyword, "round", &program::rpn_round,
|
||||
"set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward "
|
||||
"+inf\", \"toward -inf\", \"away from zero\"] round"},
|
||||
{cmd_keyword, "default", &program::rpn_default,
|
||||
"set float representation and precision to default"},
|
||||
{cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"},
|
||||
|
||||
//TESTS
|
||||
{ cmd_undef, "", NULL, "\nTEST"},
|
||||
{ cmd_keyword, ">", &program::rpn_sup, "binary operator >" },
|
||||
{ cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >=" },
|
||||
{ cmd_keyword, "<", &program::rpn_inf, "binary operator <" },
|
||||
{ cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <=" },
|
||||
{ cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)" },
|
||||
{ cmd_keyword, "==", &program::rpn_eq , "binary operator == (equal)" },
|
||||
{ cmd_keyword, "and", &program::rpn_test_and , "boolean operator and" },
|
||||
{ cmd_keyword, "or", &program::rpn_test_or , "boolean operator or" },
|
||||
{ cmd_keyword, "xor", &program::rpn_test_xor , "boolean operator xor" },
|
||||
{ cmd_keyword, "not", &program::rpn_test_not , "boolean operator not" },
|
||||
{ cmd_keyword, "same", &program::rpn_same , "boolean operator same (equal)" },
|
||||
// TESTS
|
||||
{cmd_undef, "", NULL, "\nTEST"},
|
||||
{cmd_keyword, ">", &program::rpn_sup, "binary operator >"},
|
||||
{cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="},
|
||||
{cmd_keyword, "<", &program::rpn_inf, "binary operator <"},
|
||||
{cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="},
|
||||
{cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"},
|
||||
{cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"},
|
||||
{cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"},
|
||||
{cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"},
|
||||
{cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
|
||||
{cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"},
|
||||
{cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"},
|
||||
|
||||
//STACK
|
||||
{ cmd_undef, "", NULL, "\nSTACK"},
|
||||
{ cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries" },
|
||||
{ cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry" },
|
||||
{ cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries" },
|
||||
{ cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries" },
|
||||
{ cmd_keyword, "del", &program::rpn_erase, "drop all stack entries" },
|
||||
{ cmd_keyword, "erase", &program::rpn_erase, "" },
|
||||
{ cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries" },
|
||||
{ cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry" },
|
||||
{ cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries" },
|
||||
{ cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries" },
|
||||
{ cmd_keyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack" },
|
||||
{ cmd_keyword, "depth", &program::rpn_depth, "give stack depth" },
|
||||
{ cmd_keyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack" },
|
||||
{ cmd_keyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position" },
|
||||
{ cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack" },
|
||||
// STACK
|
||||
{cmd_undef, "", NULL, "\nSTACK"},
|
||||
{cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
|
||||
{cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"},
|
||||
{cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"},
|
||||
{cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries"},
|
||||
{cmd_keyword, "del", &program::rpn_erase, "drop all stack entries"},
|
||||
{cmd_keyword, "erase", &program::rpn_erase, ""},
|
||||
{cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
|
||||
{cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
|
||||
{cmd_keyword, "dup2", &program::rpn_dup2,
|
||||
"duplicate 2 first stack entries"},
|
||||
{cmd_keyword, "dupn", &program::rpn_dupn,
|
||||
"duplicate n first stack entries"},
|
||||
{cmd_keyword, "pick", &program::rpn_pick,
|
||||
"push a copy of the given stack level onto the stack"},
|
||||
{cmd_keyword, "depth", &program::rpn_depth, "give stack depth"},
|
||||
{cmd_keyword, "roll", &program::rpn_roll,
|
||||
"move a stack entry to the top of the stack"},
|
||||
{cmd_keyword, "rolld", &program::rpn_rolld,
|
||||
"move the element on top of the stack to a higher stack position"},
|
||||
{cmd_keyword, "over", &program::rpn_over,
|
||||
"push a copy of the element in stack level 2 onto the stack"},
|
||||
|
||||
//STRING
|
||||
{ cmd_undef, "", NULL, "\nSTRING"},
|
||||
{ cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string" },
|
||||
{ cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object" },
|
||||
{ cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string" },
|
||||
{ cmd_keyword, "num", &program::rpn_num, "return ASCII code of the first character of the string in stack level 1 as a real number" },
|
||||
{ cmd_keyword, "size", &program::rpn_strsize, "return the length of the string" },
|
||||
{ cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2" },
|
||||
{ cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3" },
|
||||
// STRING
|
||||
{cmd_undef, "", NULL, "\nSTRING"},
|
||||
{cmd_keyword, "->str", &program::rpn_instr,
|
||||
"convert an object into a string"},
|
||||
{cmd_keyword, "str->", &program::rpn_strout,
|
||||
"convert a string into an object"},
|
||||
{cmd_keyword, "chr", &program::rpn_chr,
|
||||
"convert ASCII character code in stack level 1 into a string"},
|
||||
{cmd_keyword, "num", &program::rpn_num,
|
||||
"return ASCII code of the first character of the string in stack level 1 "
|
||||
"as a real number"},
|
||||
{cmd_keyword, "size", &program::rpn_strsize,
|
||||
"return the length of the string"},
|
||||
{cmd_keyword, "pos", &program::rpn_strpos,
|
||||
"seach for the string in level 1 within the string in level 2"},
|
||||
{cmd_keyword, "sub", &program::rpn_strsub,
|
||||
"return a substring of the string in level 3"},
|
||||
|
||||
//BRANCH
|
||||
{ cmd_undef, "", NULL, "\nBRANCH"},
|
||||
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "if <test-instruction> then <true-instructions> else <false-instructions> end" },
|
||||
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if" },
|
||||
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" },
|
||||
{ cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" },
|
||||
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step" },
|
||||
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "<start> <end> for <variable> <instructions> next|<step> step" },
|
||||
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" },
|
||||
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for" },
|
||||
{ cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, <test-instruction> <true-instruction> ift" },
|
||||
{ cmd_keyword, "ifte",&program::rpn_ifte, "similar to if-then-else-end, <test-instruction> <true-instruction> <false-instruction> ifte" },
|
||||
{ cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end" },
|
||||
{ cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do" },
|
||||
{ cmd_branch, "unti", (program_fn_t)&program::rpn_until, "" },
|
||||
{ cmd_branch, "while", (program_fn_t)&program::rpn_while, "while <test-instruction> repeat <loop-instructions> end" },
|
||||
{ cmd_branch, "whil", (program_fn_t)&program::rpn_while, "" },
|
||||
{ cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while" },
|
||||
{ cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, "" },
|
||||
// BRANCH
|
||||
{cmd_undef, "", NULL, "\nBRANCH"},
|
||||
{cmd_branch, "if", (program_fn_t)&program::rpn_if,
|
||||
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
||||
"end"},
|
||||
{cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"},
|
||||
{cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"},
|
||||
{cmd_branch, "end", (program_fn_t)&program::rpn_end,
|
||||
"used with various branch instructions"},
|
||||
{cmd_branch, "start", (program_fn_t)&program::rpn_start,
|
||||
"<start> <end> start <instructions> next|<step> step"},
|
||||
{cmd_branch, "for", (program_fn_t)&program::rpn_for,
|
||||
"<start> <end> for <variable> <instructions> next|<step> step"},
|
||||
{cmd_branch, "next", (program_fn_t)&program::rpn_next,
|
||||
"used with start and for"},
|
||||
{cmd_branch, "step", (program_fn_t)&program::rpn_step,
|
||||
"used with start and for"},
|
||||
{cmd_keyword, "ift", &program::rpn_ift,
|
||||
"similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||
{cmd_keyword, "ifte", &program::rpn_ifte,
|
||||
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
||||
"<false-instruction> ifte"},
|
||||
{cmd_branch, "do", (program_fn_t)&program::rpn_do,
|
||||
"do <instructions> until <condition> end"},
|
||||
{cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"},
|
||||
{cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""},
|
||||
{cmd_branch, "while", (program_fn_t)&program::rpn_while,
|
||||
"while <test-instruction> repeat <loop-instructions> end"},
|
||||
{cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""},
|
||||
{cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat,
|
||||
"used with while"},
|
||||
{cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""},
|
||||
|
||||
//STORE
|
||||
{ cmd_undef, "", NULL, "\nSTORE"},
|
||||
{ cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto" },
|
||||
{ cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl" },
|
||||
{ cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge" },
|
||||
{ cmd_keyword, "vars", &program::rpn_vars, "list all variables" },
|
||||
{ cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables" },
|
||||
{ cmd_keyword, "edit", &program::rpn_edit, "edit a variable content" },
|
||||
{ cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+" },
|
||||
{ cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-" },
|
||||
{ cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*" },
|
||||
{ cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/" },
|
||||
{ cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg" },
|
||||
{ cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv" },
|
||||
// STORE
|
||||
{cmd_undef, "", NULL, "\nSTORE"},
|
||||
{cmd_keyword, "sto", &program::rpn_sto,
|
||||
"store a variable. ex: 1 'name' sto"},
|
||||
{cmd_keyword, "rcl", &program::rpn_rcl,
|
||||
"recall a variable. ex: 'name' rcl"},
|
||||
{cmd_keyword, "purge", &program::rpn_purge,
|
||||
"delete a variable. ex: 'name' purge"},
|
||||
{cmd_keyword, "vars", &program::rpn_vars, "list all variables"},
|
||||
{cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"},
|
||||
{cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"},
|
||||
{cmd_keyword, "sto+", &program::rpn_stoadd,
|
||||
"add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||
{cmd_keyword, "sto-", &program::rpn_stosub,
|
||||
"substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||
{cmd_keyword, "sto*", &program::rpn_stomul,
|
||||
"multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||
{cmd_keyword, "sto/", &program::rpn_stodiv,
|
||||
"divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||
{cmd_keyword, "sneg", &program::rpn_stoneg,
|
||||
"negate a variable. ex: 'name' sneg"},
|
||||
{cmd_keyword, "sinv", &program::rpn_stoinv,
|
||||
"inverse a variable. ex: 1 'name' sinv"},
|
||||
|
||||
//PROGRAM
|
||||
{ cmd_undef, "", NULL, "\nPROGRAM"},
|
||||
{ cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" },
|
||||
{ cmd_branch, "->", (program_fn_t)&program::rpn_inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> >>" },
|
||||
// PROGRAM
|
||||
{cmd_undef, "", NULL, "\nPROGRAM"},
|
||||
{cmd_keyword, "eval", &program::rpn_eval,
|
||||
"evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||
{cmd_branch, "->", (program_fn_t)&program::rpn_inprog,
|
||||
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
||||
">>"},
|
||||
|
||||
//TRIG ON REALS AND COMPLEXES
|
||||
{ cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
|
||||
{ cmd_keyword, "pi", &program::rpn_pi, "pi constant" },
|
||||
{ cmd_keyword, "sin", &program::rpn_sin, "sinus" },
|
||||
{ cmd_keyword, "asin", &program::rpn_asin, "arg sinus" },
|
||||
{ cmd_keyword, "cos", &program::rpn_cos , "cosinus" },
|
||||
{ cmd_keyword, "acos", &program::rpn_acos, "arg cosinus" },
|
||||
{ cmd_keyword, "tan", &program::rpn_tan, "tangent" },
|
||||
{ cmd_keyword, "atan", &program::rpn_atan, "arg tangent" },
|
||||
{ cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians" },
|
||||
{ cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees" },
|
||||
// TRIG ON REALS AND COMPLEXES
|
||||
{cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"},
|
||||
{cmd_keyword, "pi", &program::rpn_pi, "pi constant"},
|
||||
{cmd_keyword, "sin", &program::rpn_sin, "sinus"},
|
||||
{cmd_keyword, "asin", &program::rpn_asin, "arg sinus"},
|
||||
{cmd_keyword, "cos", &program::rpn_cos, "cosinus"},
|
||||
{cmd_keyword, "acos", &program::rpn_acos, "arg cosinus"},
|
||||
{cmd_keyword, "tan", &program::rpn_tan, "tangent"},
|
||||
{cmd_keyword, "atan", &program::rpn_atan, "arg tangent"},
|
||||
{cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
|
||||
{cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
|
||||
|
||||
//LOGS ON REALS AND COMPLEXES
|
||||
{ cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
|
||||
{ cmd_keyword, "e", &program::rpn_e, "Euler constant" },
|
||||
{ cmd_keyword, "ln", &program::rpn_ln, "logarithm base e" },
|
||||
{ cmd_keyword, "log", &program::rpn_ln, "" },
|
||||
{ cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0" },
|
||||
{ cmd_keyword, "exp", &program::rpn_exp, "exponential" },
|
||||
{ cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0" },
|
||||
{ cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10" },
|
||||
{ cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10" },
|
||||
{ cmd_keyword, "exp10", &program::rpn_alog10, "" },
|
||||
{ cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2" },
|
||||
{ cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2" },
|
||||
{ cmd_keyword, "exp2", &program::rpn_alog2, "" },
|
||||
{ cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine" },
|
||||
{ cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine" },
|
||||
{ cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine" },
|
||||
{ cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine" },
|
||||
{ cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent" },
|
||||
{ cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent" },
|
||||
// LOGS ON REALS AND COMPLEXES
|
||||
{cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"},
|
||||
{cmd_keyword, "e", &program::rpn_e, "Euler constant"},
|
||||
{cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"},
|
||||
{cmd_keyword, "log", &program::rpn_ln, ""},
|
||||
{cmd_keyword, "lnp1", &program::rpn_lnp1,
|
||||
"ln(1+x) which is useful when x is close to 0"},
|
||||
{cmd_keyword, "exp", &program::rpn_exp, "exponential"},
|
||||
{cmd_keyword, "expm", &program::rpn_expm,
|
||||
"exp(x)-1 which is useful when x is close to 0"},
|
||||
{cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"},
|
||||
{cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"},
|
||||
{cmd_keyword, "exp10", &program::rpn_alog10, ""},
|
||||
{cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"},
|
||||
{cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"},
|
||||
{cmd_keyword, "exp2", &program::rpn_alog2, ""},
|
||||
{cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
|
||||
{cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
|
||||
{cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine"},
|
||||
{cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"},
|
||||
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
||||
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
|
||||
|
||||
// end
|
||||
{ cmd_max, "", NULL, "" },
|
||||
{cmd_max, "", NULL, ""},
|
||||
};
|
||||
|
|
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)
|
||||
{
|
||||
// myobj.arg1 = 'if' condition evaluation value
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
int rpn_if(branch& myobj) {
|
||||
// myobj.arg1 = 'if' condition evaluation value
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
|
||||
myobj.arg1 = 1;
|
||||
else
|
||||
myobj.arg1 = 0;
|
||||
(void)_stack->pop_back();
|
||||
return -1;
|
||||
if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
|
||||
myobj.arg1 = 1;
|
||||
else
|
||||
myobj.arg1 = 0;
|
||||
(void)_stack->pop_back();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_then(branch& myobj)
|
||||
{
|
||||
// myobj.arg1 = index of then + 1
|
||||
// myobj.arg2 = index of else + 1 or end + 1
|
||||
// myobj.arg3 = index of if
|
||||
// if condition is true -> arg1 (= jump to then + 1)
|
||||
// else -> arg2 (= jump to else + 1 or end + 1)
|
||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||
if (if_cmd->arg1 == 1)
|
||||
return myobj.arg1;
|
||||
else
|
||||
return myobj.arg2;
|
||||
int rpn_then(branch& myobj) {
|
||||
// myobj.arg1 = index of then + 1
|
||||
// myobj.arg2 = index of else + 1 or end + 1
|
||||
// myobj.arg3 = index of if
|
||||
// if condition is true -> arg1 (= jump to then + 1)
|
||||
// else -> arg2 (= jump to else + 1 or end + 1)
|
||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||
if (if_cmd->arg1 == 1)
|
||||
return myobj.arg1;
|
||||
else
|
||||
return myobj.arg2;
|
||||
}
|
||||
|
||||
int rpn_else(branch& myobj)
|
||||
{
|
||||
// myobj.arg1 = index of else + 1
|
||||
// myobj.arg2 = index of end + 1
|
||||
// myobj.arg3 = index of if
|
||||
// if condition was false -> arg1 (= jump to else + 1)
|
||||
// if condition was true -> arg2 (= jump to end + 1)
|
||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||
if (if_cmd->arg1 == 1)
|
||||
return myobj.arg2;
|
||||
else
|
||||
return myobj.arg1;
|
||||
int rpn_else(branch& myobj) {
|
||||
// myobj.arg1 = index of else + 1
|
||||
// myobj.arg2 = index of end + 1
|
||||
// myobj.arg3 = index of if
|
||||
// if condition was false -> arg1 (= jump to else + 1)
|
||||
// if condition was true -> arg2 (= jump to end + 1)
|
||||
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||||
if (if_cmd->arg1 == 1)
|
||||
return myobj.arg2;
|
||||
else
|
||||
return myobj.arg1;
|
||||
}
|
||||
|
||||
int rpn_end(branch& myobj)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
// arg1 = index of do+1 in case of do..unti..end
|
||||
if (myobj.arg1 != -1)
|
||||
{
|
||||
// in a template do..unti..end
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// check arg
|
||||
number* arg = (number*)_stack->pop_back();
|
||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
|
||||
ret = myobj.arg1;
|
||||
}
|
||||
// arg2 = index of while+1 in case of while..repeat..end
|
||||
else if (myobj.arg2 != -1)
|
||||
ret = myobj.arg2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_do(branch& myobj)
|
||||
{
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_until(branch& myobj)
|
||||
{
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
void rpn_ift(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
// check ift arg
|
||||
// arg is true if number != 0 or if is nan or +/-inf
|
||||
number* testee = ((number*)_stack->get_obj(1));
|
||||
|
||||
if (!mpfr_zero_p(testee->_value.mpfr))
|
||||
{
|
||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
|
||||
(void)_stack->pop_back(2);
|
||||
|
||||
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
|
||||
(void)_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
(void)_stack->pop_back(2);
|
||||
}
|
||||
|
||||
void rpn_ifte(void)
|
||||
{
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(2, cmd_number);
|
||||
|
||||
// check ifte arg
|
||||
// arg is true if number != 0 or if is nan or +/-inf
|
||||
number* testee = ((number*)_stack->get_obj(2));
|
||||
|
||||
if (!mpfr_zero_p(testee->_value.mpfr))
|
||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack));
|
||||
else
|
||||
CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack));
|
||||
|
||||
(void)_stack->pop_back(3);
|
||||
|
||||
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack));
|
||||
(void)_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
int rpn_while(branch& myobj)
|
||||
{
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_repeat(branch& myobj)
|
||||
{
|
||||
int ret = -1;
|
||||
int rpn_end(branch& myobj) {
|
||||
int ret = -1;
|
||||
|
||||
// arg1 = index of do+1 in case of do..unti..end
|
||||
if (myobj.arg1 != -1) {
|
||||
// in a template do..unti..end
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// check arg
|
||||
// myobj.arg1 is end+1
|
||||
number* arg = (number*)_stack->pop_back();
|
||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
|
||||
ret = myobj.arg1;
|
||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
|
||||
}
|
||||
// arg2 = index of while+1 in case of while..repeat..end
|
||||
else if (myobj.arg2 != -1)
|
||||
ret = myobj.arg2;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_start(branch& myobj)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// farg2 = last value of start command
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
myobj.farg2 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// farg1 = first value of start command
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
myobj.farg1 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// test value
|
||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||
// last boundary lower than first boundary
|
||||
// -> next command shall be after 'next'
|
||||
// arg2 holds index of 'next'
|
||||
ret = myobj.arg2 + 1;
|
||||
|
||||
return ret;
|
||||
int rpn_do(branch& myobj) {
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_for(branch& myobj)
|
||||
{
|
||||
int ret;
|
||||
int rpn_until(branch& myobj) {
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||
//
|
||||
void rpn_ift(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
|
||||
// check ift arg
|
||||
// arg is true if number != 0 or if is nan or +/-inf
|
||||
number* testee = ((number*)_stack->get_obj(1));
|
||||
|
||||
// farg2 = last value of for command
|
||||
// arg1 = index of symbol to increase
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
myobj.farg2 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
if (!mpfr_zero_p(testee->_value.mpfr)) {
|
||||
CHECK_MPFR(
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
|
||||
(void)_stack->pop_back(2);
|
||||
|
||||
// farg1 = first value of for command
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
myobj.farg1 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1,
|
||||
*_stack));
|
||||
(void)_calc_stack.pop_back();
|
||||
} else
|
||||
(void)_stack->pop_back(2);
|
||||
}
|
||||
|
||||
// test value
|
||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||
// last boundary lower than first boundary
|
||||
// -> next command shall be after 'next'
|
||||
// arg2 holds index of 'next'
|
||||
ret = myobj.arg2 + 1;
|
||||
void rpn_ifte(void) {
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(2, cmd_number);
|
||||
|
||||
// check ifte arg
|
||||
// arg is true if number != 0 or if is nan or +/-inf
|
||||
number* testee = ((number*)_stack->get_obj(2));
|
||||
|
||||
if (!mpfr_zero_p(testee->_value.mpfr))
|
||||
CHECK_MPFR(
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack));
|
||||
else
|
||||
CHECK_MPFR(
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack));
|
||||
|
||||
(void)_stack->pop_back(3);
|
||||
|
||||
CHECK_MPFR(
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack));
|
||||
(void)_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
int rpn_while(branch& myobj) {
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_repeat(branch& myobj) {
|
||||
int ret = -1;
|
||||
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// check arg
|
||||
// myobj.arg1 is end+1
|
||||
number* arg = (number*)_stack->pop_back();
|
||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_start(branch& myobj) {
|
||||
int ret = -1;
|
||||
|
||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// farg2 = last value of start command
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
myobj.farg2 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// farg1 = first value of start command
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
myobj.farg1 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// test value
|
||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||
// last boundary lower than first boundary
|
||||
// -> next command shall be after 'next'
|
||||
// arg2 holds index of 'next'
|
||||
ret = myobj.arg2 + 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_for(branch& myobj) {
|
||||
int ret;
|
||||
|
||||
MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
|
||||
|
||||
// farg2 = last value of for command
|
||||
// arg1 = index of symbol to increase
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
myobj.farg2 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// farg1 = first value of for command
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
myobj.farg1 = (number*)_calc_stack.back();
|
||||
_stack->pop_back();
|
||||
|
||||
// test value
|
||||
if (myobj.farg1->_value > myobj.farg2->_value)
|
||||
// last boundary lower than first boundary
|
||||
// -> next command shall be after 'next'
|
||||
// arg2 holds index of 'next'
|
||||
ret = myobj.arg2 + 1;
|
||||
else {
|
||||
// store symbol with first value
|
||||
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
|
||||
ret = myobj.arg1 + 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_next(branch& myobj) {
|
||||
// arg1 = index of start or for command in program
|
||||
// farg1 = current count
|
||||
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
||||
if (!myobj.arg_bool) {
|
||||
myobj.arg_bool = true;
|
||||
myobj.farg1 = start_or_for->farg1;
|
||||
}
|
||||
|
||||
// increment then test
|
||||
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL,
|
||||
MPFR_DEFAULT_RND);
|
||||
|
||||
// for command: increment symbol too
|
||||
if (start_or_for->arg1 != -1) {
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
|
||||
// increase symbol variable
|
||||
_local_heap.replace_value(string(var->_value), myobj.farg1,
|
||||
myobj.farg1->size());
|
||||
}
|
||||
|
||||
// test value
|
||||
if (myobj.farg1->_value > start_or_for->farg2->_value) {
|
||||
// end of loop
|
||||
myobj.arg_bool = false; // init again next time
|
||||
_calc_stack.pop_back(2);
|
||||
return -1;
|
||||
} else {
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
{
|
||||
// store symbol with first value
|
||||
_local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size());
|
||||
ret = myobj.arg1 + 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return myobj.arg1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int rpn_next(branch& myobj)
|
||||
{
|
||||
int rpn_step(branch& myobj) {
|
||||
int ret;
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
number* step = (number*)_stack->pop_back();
|
||||
|
||||
// end of loop if step is negative or zero
|
||||
if (mpfr_cmp_d(step->_value.mpfr, 0.0) <= 0)
|
||||
ret = -1;
|
||||
else {
|
||||
// arg1 = index of start or for command in program
|
||||
// farg1 = current count
|
||||
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
||||
if (! myobj.arg_bool)
|
||||
{
|
||||
myobj.arg_bool = true;
|
||||
myobj.farg1 = start_or_for->farg1;
|
||||
if (!myobj.arg_bool) {
|
||||
myobj.arg_bool = true;
|
||||
myobj.farg1 = start_or_for->farg1;
|
||||
}
|
||||
|
||||
// increment then test
|
||||
mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL, MPFR_DEFAULT_RND);
|
||||
mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr,
|
||||
step->_value.mpfr, MPFR_DEFAULT_RND);
|
||||
|
||||
// for command: increment symbol too
|
||||
if (start_or_for->arg1 != -1)
|
||||
{
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
if (start_or_for->arg1 != -1) {
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
|
||||
// increase symbol variable
|
||||
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
|
||||
// increase symbol variable
|
||||
_local_heap.replace_value(string(var->_value), myobj.farg1,
|
||||
myobj.farg1->size());
|
||||
}
|
||||
|
||||
//test value
|
||||
if (myobj.farg1->_value > start_or_for->farg2->_value)
|
||||
{
|
||||
// end of loop
|
||||
myobj.arg_bool = false;// init again next time
|
||||
_calc_stack.pop_back(2);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1)
|
||||
return start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
return myobj.arg1 + 1;
|
||||
// test loop value is out of range
|
||||
if (myobj.farg1->_value > start_or_for->farg2->_value) {
|
||||
// end of loop
|
||||
myobj.arg_bool = false; // init again next time
|
||||
_calc_stack.pop_back(2);
|
||||
ret = -1;
|
||||
} else {
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
ret = myobj.arg1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int rpn_step(branch& myobj)
|
||||
{
|
||||
int ret;
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
number* step = (number*)_stack->pop_back();
|
||||
|
||||
// end of loop if step is negative or zero
|
||||
if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0)
|
||||
ret = -1;
|
||||
else
|
||||
{
|
||||
// arg1 = index of start or for command in program
|
||||
// farg1 = current count
|
||||
branch* start_or_for = (branch*)seq_obj(myobj.arg1);
|
||||
if (! myobj.arg_bool)
|
||||
{
|
||||
myobj.arg_bool = true;
|
||||
myobj.farg1 = start_or_for->farg1;
|
||||
}
|
||||
|
||||
// increment then test
|
||||
mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEFAULT_RND);
|
||||
|
||||
// for command: increment symbol too
|
||||
if (start_or_for->arg1 != -1)
|
||||
{
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
|
||||
// increase symbol variable
|
||||
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
|
||||
}
|
||||
|
||||
// test loop value is out of range
|
||||
if (myobj.farg1->_value > start_or_for->farg2->_value)
|
||||
{
|
||||
// end of loop
|
||||
myobj.arg_bool = false;// init again next time
|
||||
_calc_stack.pop_back(2);
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1)
|
||||
ret = start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
ret = myobj.arg1 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,130 +1,146 @@
|
|||
void rpn_re()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
void rpn_re() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set(re->_value.mpfr,
|
||||
((complex*)_calc_stack.get_obj(0))->re()->mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
void rpn_im()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
void rpn_im() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set(im->_value.mpfr,
|
||||
((complex*)_calc_stack.get_obj(0))->im()->mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
void rpn_arg()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
void rpn_arg() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
// calc atan2(x/y)
|
||||
complex* cplx = (complex*)_stack->pop_back();
|
||||
number* num = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||
// calc atan2(x/y)
|
||||
complex* cplx = (complex*)_stack->pop_back();
|
||||
number* num =
|
||||
(number*)_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||
|
||||
CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
_calc_stack.pop_back();
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
void rpn_conj()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
void rpn_conj() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
complex* cplx = (complex*)_stack->back();
|
||||
CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
complex* cplx = (complex*)_stack->back();
|
||||
CHECK_MPFR(
|
||||
mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
||||
void rpn_r2c()
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
_stack->pop_back();
|
||||
void rpn_r2c() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.get_obj(1))->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back(2);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
_stack->pop_back();
|
||||
|
||||
complex* cplx =
|
||||
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr,
|
||||
((number*)_calc_stack.get_obj(1))->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr,
|
||||
((number*)_calc_stack.get_obj(0))->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
|
||||
void rpn_c2r()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
void rpn_c2r() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
|
||||
CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
CHECK_MPFR(mpfr_set(re->_value.mpfr,
|
||||
((complex*)_calc_stack.back())->re()->mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set(im->_value.mpfr,
|
||||
((complex*)_calc_stack.back())->im()->mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
|
||||
void rpn_r2p()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
void rpn_r2p() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
rpn_dup();
|
||||
rpn_dup();
|
||||
rpn_arg();
|
||||
rpn_dup();
|
||||
rpn_dup();
|
||||
rpn_arg();
|
||||
|
||||
complex* cplx = (complex*)_stack->get_obj(1);
|
||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
_stack->pop_back();
|
||||
|
||||
rpn_swap();
|
||||
rpn_abs();
|
||||
cplx = (complex*)_stack->get_obj(1);
|
||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
_stack->pop_back();
|
||||
complex* cplx = (complex*)_stack->get_obj(1);
|
||||
CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_stack->pop_back();
|
||||
|
||||
rpn_swap();
|
||||
rpn_abs();
|
||||
cplx = (complex*)_stack->get_obj(1);
|
||||
CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
||||
void rpn_p2r()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
void rpn_p2r() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_complex);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||
|
||||
// assert complex is polar
|
||||
complex* rhotheta = (complex*)_calc_stack.get_obj(1);
|
||||
number* tmp = (number*)_calc_stack.get_obj(0);
|
||||
complex* result = (complex*)_stack->back();
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_calc_stack.allocate_back(number::calc_size(), cmd_number);
|
||||
|
||||
//calc cos(theta)
|
||||
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
// assert complex is polar
|
||||
complex* rhotheta = (complex*)_calc_stack.get_obj(1);
|
||||
number* tmp = (number*)_calc_stack.get_obj(0);
|
||||
complex* result = (complex*)_stack->back();
|
||||
|
||||
//calc rcos(theta)
|
||||
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
// calc cos(theta)
|
||||
CHECK_MPFR(
|
||||
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(
|
||||
mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
//calc sin(theta)
|
||||
CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
// calc rcos(theta)
|
||||
CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr,
|
||||
tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
//calc rsin(theta)
|
||||
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
// calc sin(theta)
|
||||
CHECK_MPFR(
|
||||
mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(
|
||||
mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
// calc rsin(theta)
|
||||
CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr,
|
||||
tmp->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
|
|
@ -1,230 +1,209 @@
|
|||
//
|
||||
void rpn_nop()
|
||||
{
|
||||
// nop
|
||||
void rpn_nop() {
|
||||
// nop
|
||||
}
|
||||
|
||||
void rpn_good_bye()
|
||||
{
|
||||
ERR_CONTEXT(ret_good_bye);
|
||||
}
|
||||
void rpn_good_bye() { ERR_CONTEXT(ret_good_bye); }
|
||||
|
||||
void rpn_help()
|
||||
{
|
||||
// software name
|
||||
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
|
||||
void rpn_help() {
|
||||
// software name
|
||||
printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname);
|
||||
|
||||
// description
|
||||
printf("%s\n\n", description);
|
||||
// description
|
||||
printf("%s\n\n", description);
|
||||
|
||||
// syntax
|
||||
printf("%s\n", syntax);
|
||||
// syntax
|
||||
printf("%s\n", syntax);
|
||||
|
||||
// keywords
|
||||
unsigned int i = 0;
|
||||
while(s_keywords[i].type != cmd_max)
|
||||
{
|
||||
if (s_keywords[i].comment.size() != 0)
|
||||
{
|
||||
// titles in bold
|
||||
if (s_keywords[i].type==cmd_undef)
|
||||
printf(ATTR_BOLD);
|
||||
// show title or keyword + comment
|
||||
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
|
||||
if (s_keywords[i].type==cmd_undef)
|
||||
printf(ATTR_OFF);
|
||||
}
|
||||
i++;
|
||||
// keywords
|
||||
unsigned int i = 0;
|
||||
while (s_keywords[i].type != cmd_max) {
|
||||
if (s_keywords[i].comment.size() != 0) {
|
||||
// titles in bold
|
||||
if (s_keywords[i].type == cmd_undef) printf(ATTR_BOLD);
|
||||
// show title or keyword + comment
|
||||
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
|
||||
if (s_keywords[i].type == cmd_undef) printf(ATTR_OFF);
|
||||
}
|
||||
printf("\n");
|
||||
i++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// show mode
|
||||
printf("Current float mode is ");
|
||||
switch(number::s_mode)
|
||||
{
|
||||
case number::std: printf("'std'"); break;
|
||||
case number::fix: printf("'fix'"); break;
|
||||
case number::sci: printf("'sci'"); break;
|
||||
default: printf("unknown"); break;
|
||||
// show mode
|
||||
printf("Current float mode is ");
|
||||
switch (number::s_mode) {
|
||||
case number::std:
|
||||
printf("'std'");
|
||||
break;
|
||||
case number::fix:
|
||||
printf("'fix'");
|
||||
break;
|
||||
case number::sci:
|
||||
printf("'sci'");
|
||||
break;
|
||||
default:
|
||||
printf("unknown");
|
||||
break;
|
||||
}
|
||||
printf(" with %d digits after the decimal point\n", number::s_decimal_digits);
|
||||
|
||||
// bits precision, decimal digits and rounding mode
|
||||
printf("Current floating point precision is %d bits\n",
|
||||
(int)floating_t::s_mpfr_prec);
|
||||
printf("Current rounding mode is \"%s\"\n",
|
||||
floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
int base_digits_from_bit_precision(int base, int bit_precision) {
|
||||
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
|
||||
}
|
||||
|
||||
string make_digit_format(int decimal_digits, const char* printf_format) {
|
||||
stringstream ss;
|
||||
ss << MPFR_FORMAT_BEG;
|
||||
ss << number::s_decimal_digits;
|
||||
ss << printf_format;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool check_decimal_digits(double precision) {
|
||||
bool ret = true;
|
||||
|
||||
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
||||
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
||||
double prec_max = (double)MPFR_PREC_MAX;
|
||||
double prec_min = 0.0;
|
||||
|
||||
if (precision < prec_min || precision > prec_max) ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rpn_std() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits)) {
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::std;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format =
|
||||
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
} else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_fix() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits)) {
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::fix;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format =
|
||||
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
|
||||
} else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_sci() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits)) {
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::sci;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format =
|
||||
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI);
|
||||
} else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_version() {
|
||||
// allocate and set object
|
||||
unsigned int naked_entry_len = strlen(version);
|
||||
ostring* str = (ostring*)_stack->allocate_back(
|
||||
sizeof(ostring) + naked_entry_len + 1, cmd_string);
|
||||
str->set(version, naked_entry_len);
|
||||
}
|
||||
|
||||
void rpn_uname() {
|
||||
// allocate and set object
|
||||
unsigned int naked_entry_len = strlen(uname);
|
||||
ostring* str = (ostring*)_stack->allocate_back(
|
||||
sizeof(ostring) + naked_entry_len + 1, cmd_string);
|
||||
str->set(uname, naked_entry_len);
|
||||
}
|
||||
|
||||
void rpn_history() {
|
||||
// see command history on stdout
|
||||
int index = 0;
|
||||
char* line = linenoiseHistoryLine(index);
|
||||
while (line != NULL) {
|
||||
cout << line << endl;
|
||||
free(line);
|
||||
line = linenoiseHistoryLine(++index);
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_type() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
int type = _stack->pop_back()->_type;
|
||||
if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef;
|
||||
|
||||
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
|
||||
unsigned int size = sizeof(symbol) + string_size + 1;
|
||||
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
|
||||
typ->set(object::s_cmd_type_string[type], string_size);
|
||||
}
|
||||
|
||||
void rpn_default() { program::apply_default(); }
|
||||
|
||||
void rpn_precision() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
// set precision
|
||||
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
if (prec >= (unsigned long)MPFR_PREC_MIN &&
|
||||
prec <= (unsigned long)MPFR_PREC_MAX) {
|
||||
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
|
||||
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
|
||||
|
||||
// modify digits seen by user if std mode
|
||||
if (number::s_mode == number::std) {
|
||||
// calc max nb of digits user can see with the current bit precision
|
||||
number::s_decimal_digits =
|
||||
base_digits_from_bit_precision(10, floating_t::s_mpfr_prec);
|
||||
number::s_mpfr_printf_format =
|
||||
make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
}
|
||||
printf(" with %d digits after the decimal point\n", number::s_decimal_digits);
|
||||
|
||||
// bits precision, decimal digits and rounding mode
|
||||
printf("Current floating point precision is %d bits\n", (int)floating_t::s_mpfr_prec);
|
||||
printf("Current rounding mode is \"%s\"\n", floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
|
||||
printf("\n\n");
|
||||
} else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
int base_digits_from_bit_precision(int base, int bit_precision)
|
||||
{
|
||||
return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1;
|
||||
}
|
||||
void rpn_round() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
string make_digit_format(int decimal_digits, const char* printf_format)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << MPFR_FORMAT_BEG;
|
||||
ss << number::s_decimal_digits;
|
||||
ss << printf_format;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool check_decimal_digits(double precision)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
// MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h)
|
||||
// this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF)
|
||||
double prec_max = (double)MPFR_PREC_MAX;
|
||||
double prec_min = 0.0;
|
||||
|
||||
if (precision < prec_min || precision > prec_max)
|
||||
ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rpn_std()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits))
|
||||
{
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::std;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
ostring* str = (ostring*)_stack->pop_back();
|
||||
bool done = false;
|
||||
for (int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++) {
|
||||
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value) {
|
||||
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_fix()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits))
|
||||
{
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::fix;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_sci()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
double digits = double(((number*)_stack->pop_back())->_value);
|
||||
|
||||
if (check_decimal_digits(digits))
|
||||
{
|
||||
// set mode, decimal digits and print format
|
||||
number::s_mode = number::sci;
|
||||
number::s_decimal_digits = (int)digits;
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_version()
|
||||
{
|
||||
// allocate and set object
|
||||
unsigned int naked_entry_len = strlen(version);
|
||||
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
|
||||
str->set(version, naked_entry_len);
|
||||
}
|
||||
|
||||
void rpn_uname()
|
||||
{
|
||||
// allocate and set object
|
||||
unsigned int naked_entry_len = strlen(uname);
|
||||
ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
|
||||
str->set(uname, naked_entry_len);
|
||||
}
|
||||
|
||||
void rpn_history()
|
||||
{
|
||||
//see command history on stdout
|
||||
int index = 0;
|
||||
char* line = linenoiseHistoryLine(index);
|
||||
while(line != NULL)
|
||||
{
|
||||
cout<<line<<endl;
|
||||
free(line);
|
||||
line = linenoiseHistoryLine(++index);
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_type()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
int type = _stack->pop_back()->_type;
|
||||
if (type < 0 || type >= (int)cmd_max)
|
||||
type = (int)cmd_undef;
|
||||
|
||||
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
|
||||
unsigned int size = sizeof(symbol)+string_size+1;
|
||||
ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string);
|
||||
typ->set(object::s_cmd_type_string[type], string_size);
|
||||
}
|
||||
|
||||
void rpn_default()
|
||||
{
|
||||
program::apply_default();
|
||||
}
|
||||
|
||||
void rpn_precision()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
//set precision
|
||||
unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
if (prec>=(unsigned long)MPFR_PREC_MIN && prec<=(unsigned long)MPFR_PREC_MAX)
|
||||
{
|
||||
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
|
||||
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
|
||||
|
||||
// modify digits seen by user if std mode
|
||||
if (number::s_mode == number::std)
|
||||
{
|
||||
// calc max nb of digits user can see with the current bit precision
|
||||
number::s_decimal_digits = base_digits_from_bit_precision(10, floating_t::s_mpfr_prec);
|
||||
number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD);
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
||||
void rpn_round()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
ostring* str = (ostring*)_stack->pop_back();
|
||||
bool done = false;
|
||||
for(int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++)
|
||||
{
|
||||
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value)
|
||||
{
|
||||
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
if (!done)
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
if (!done) ERR_CONTEXT(ret_out_of_range);
|
||||
}
|
||||
|
|
570
src/rpn-logs.hpp
570
src/rpn-logs.hpp
|
@ -1,377 +1,337 @@
|
|||
void rpn_e(void)
|
||||
{
|
||||
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
euler->_value = 1L;
|
||||
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
void rpn_e(void) {
|
||||
number* euler =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
euler->_value = 1L;
|
||||
CHECK_MPFR(
|
||||
mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
||||
void rpn_log10()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_log10() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
//log10(z)=ln(z)/ln(10)
|
||||
rpn_ln();
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
// log10(z)=ln(z)/ln(10)
|
||||
rpn_ln();
|
||||
|
||||
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_div();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
number* ten =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_div();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_alog10()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_alog10() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_mul();
|
||||
rpn_exp();
|
||||
}
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
number* ten =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_mul();
|
||||
rpn_exp();
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_log2()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_log2() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
//log2(z)=ln(z)/ln(2)
|
||||
rpn_ln();
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
// log2(z)=ln(z)/ln(2)
|
||||
rpn_ln();
|
||||
|
||||
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_div();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
number* two =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_div();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_alog2()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_alog2() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_mul();
|
||||
rpn_exp();
|
||||
}
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
number* two =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_ln();
|
||||
rpn_mul();
|
||||
rpn_exp();
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_ln()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_ln() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
number* left = (number*)_stack->back();
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
// x<0 -> ln(x) = ln(-x)+i*pi
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0)
|
||||
{
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
left = (number*)_calc_stack.back();
|
||||
// x<0 -> ln(x) = ln(-x)+i*pi
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) {
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
left = (number*)_calc_stack.back();
|
||||
|
||||
complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
complex* cplx =
|
||||
(complex*)_stack->allocate_back(complex::calc_size(), cmd_complex);
|
||||
CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(
|
||||
mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd));
|
||||
_calc_stack.pop_back();
|
||||
} else
|
||||
CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
// 1. atan(x/y)
|
||||
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
// 1. atan(x/y)
|
||||
CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
// 2. 0.5*ln(x*x+y*y)
|
||||
CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
// 2. 0.5*ln(x*x+y*y)
|
||||
CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
_calc_stack.pop_back();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_exp()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_exp() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// exp(x)*(cos(y)+i sin(y))
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// exp(x)*(cos(y)+i sin(y))
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(0))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(0))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
_calc_stack.pop_back();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_expm()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_expm() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
//exp(x)-1
|
||||
rpn_exp();
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
// exp(x)-1
|
||||
rpn_exp();
|
||||
|
||||
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
number* one =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_lnp1()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_lnp1() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
//ln(x+1)
|
||||
number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) {
|
||||
// ln(x+1)
|
||||
number* one =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
|
||||
rpn_ln();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
rpn_ln();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_sinh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_sinh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
floating_t* tmp =
|
||||
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||
->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
_calc_stack.pop_back(2);
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_asinh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_asinh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// asinh(z)=ln(z+sqrt(1+z*z))
|
||||
rpn_dup();
|
||||
rpn_square();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_squareroot();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// asinh(z)=ln(z+sqrt(1+z*z))
|
||||
rpn_dup();
|
||||
rpn_square();
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_squareroot();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_cosh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_cosh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
floating_t* tmp =
|
||||
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||
->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
_calc_stack.pop_back(2);
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_acosh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_acosh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// acosh(z)=ln(z+sqrt(z+1)sqrt(z-1))
|
||||
rpn_dup();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_dup();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_mul();
|
||||
rpn_squareroot();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// acosh(z)=ln(z+sqrt(z+1)sqrt(z-1))
|
||||
rpn_dup();
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_dup();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_mul();
|
||||
rpn_squareroot();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_tanh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_tanh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
|
||||
rpn_dup();
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y))
|
||||
rpn_dup();
|
||||
|
||||
floating_t* x = ((complex*)_stack->get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_stack->get_obj(1))->im();
|
||||
floating_t* x = ((complex*)_stack->get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_stack->get_obj(1))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(1))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(1))->im();
|
||||
floating_t* re = ((complex*)_stack->get_obj(1))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(1))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_div();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_div();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_atanh()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_atanh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// atanh(z)=0.5*ln((1+z)/(1-z))
|
||||
rpn_dup();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_swap();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
rpn_div();
|
||||
rpn_ln();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
rpn_mul();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// atanh(z)=0.5*ln((1+z)/(1-z))
|
||||
rpn_dup();
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();
|
||||
rpn_swap();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
rpn_div();
|
||||
rpn_ln();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
rpn_mul();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
|
|
@ -1,167 +1,139 @@
|
|||
//
|
||||
bool find_variable(string& variable, object*& obj, unsigned int& size)
|
||||
{
|
||||
bool found = false;
|
||||
program* parent = _parent_prog;
|
||||
bool find_variable(string& variable, object*& obj, unsigned int& size) {
|
||||
bool found = false;
|
||||
program* parent = _parent_prog;
|
||||
|
||||
// find variable in local heap, parens heaps, global heap
|
||||
if (_local_heap.get(variable, obj, size))
|
||||
// find variable in local heap, parens heaps, global heap
|
||||
if (_local_heap.get(variable, obj, size))
|
||||
found = true;
|
||||
else {
|
||||
while (parent != NULL) {
|
||||
if (parent->_local_heap.get(variable, obj, size)) {
|
||||
found = true;
|
||||
else
|
||||
{
|
||||
while(parent != NULL)
|
||||
{
|
||||
if (parent->_local_heap.get(variable, obj, size))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
parent = parent->_parent_prog;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
if (_heap->get(variable, obj, size))
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
parent = parent->_parent_prog;
|
||||
}
|
||||
|
||||
return found;
|
||||
if (!found) {
|
||||
if (_heap->get(variable, obj, size)) found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void rpn_eval(void)
|
||||
{
|
||||
bool run_prog = false;
|
||||
string prog_text;
|
||||
void rpn_eval(void) {
|
||||
bool run_prog = false;
|
||||
string prog_text;
|
||||
|
||||
MIN_ARGUMENTS(1);
|
||||
if (IS_ARG_TYPE(0, cmd_symbol))
|
||||
{
|
||||
// recall a variable
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
|
||||
// if variable holds a program, run this program
|
||||
if (find_variable(variable, obj, size))
|
||||
{
|
||||
if (obj->_type == cmd_program)
|
||||
{
|
||||
prog_text = ((oprogram*)obj)->_value;
|
||||
(void)_stack->pop_back();
|
||||
run_prog = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// else recall this variable (i.e. stack its content)
|
||||
(void)_stack->pop_back();
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
else if (IS_ARG_TYPE(0, cmd_program))
|
||||
{
|
||||
// eval a program
|
||||
prog_text = ((oprogram*)_stack->pop_back())->_value;
|
||||
MIN_ARGUMENTS(1);
|
||||
if (IS_ARG_TYPE(0, cmd_symbol)) {
|
||||
// recall a variable
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
|
||||
// if variable holds a program, run this program
|
||||
if (find_variable(variable, obj, size)) {
|
||||
if (obj->_type == cmd_program) {
|
||||
prog_text = ((oprogram*)obj)->_value;
|
||||
(void)_stack->pop_back();
|
||||
run_prog = true;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
} else {
|
||||
// else recall this variable (i.e. stack its content)
|
||||
(void)_stack->pop_back();
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
} else if (IS_ARG_TYPE(0, cmd_program)) {
|
||||
// eval a program
|
||||
prog_text = ((oprogram*)_stack->pop_back())->_value;
|
||||
run_prog = true;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
|
||||
// run prog if any
|
||||
if (run_prog)
|
||||
{
|
||||
program prog(this);
|
||||
// run prog if any
|
||||
if (run_prog) {
|
||||
program prog(this);
|
||||
|
||||
// make program from entry
|
||||
if (program::parse(prog_text.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
// make program from entry
|
||||
if (program::parse(prog_text.c_str(), prog) == ret_ok) {
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// carefull, this not a command but a branch
|
||||
int rpn_inprog(branch& myobj)
|
||||
{
|
||||
string context("->");// for showing errors
|
||||
int count_symbols = 0;
|
||||
bool prog_found = false;
|
||||
int rpn_inprog(branch& myobj) {
|
||||
string context("->"); // for showing errors
|
||||
int count_symbols = 0;
|
||||
bool prog_found = false;
|
||||
|
||||
if (myobj.arg1 == -1)
|
||||
{
|
||||
ERR_CONTEXT(ret_unknown_err);
|
||||
return -1;
|
||||
if (myobj.arg1 == -1) {
|
||||
ERR_CONTEXT(ret_unknown_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// syntax must be
|
||||
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
|
||||
|
||||
// find next oprogram object
|
||||
for (unsigned int i = myobj.arg1 + 1; i < size(); i++) {
|
||||
// count symbol
|
||||
if (seq_type(i) == cmd_symbol) count_symbols++;
|
||||
// stop if prog
|
||||
else if (seq_type(i) == cmd_program) {
|
||||
prog_found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// syntax must be
|
||||
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
|
||||
|
||||
// find next oprogram object
|
||||
for (unsigned int i = myobj.arg1 + 1; i < size(); i++)
|
||||
{
|
||||
// count symbol
|
||||
if (seq_type(i) == cmd_symbol)
|
||||
count_symbols++;
|
||||
// stop if prog
|
||||
else if (seq_type(i) == cmd_program)
|
||||
{
|
||||
prog_found = true;
|
||||
break;
|
||||
}
|
||||
// found something other than symbol
|
||||
else
|
||||
{
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
// found something other than symbol
|
||||
else {
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// found 0 symbols
|
||||
if (count_symbols == 0)
|
||||
{
|
||||
ERR_CONTEXT(ret_syntax);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
// found 0 symbols
|
||||
if (count_symbols == 0) {
|
||||
ERR_CONTEXT(ret_syntax);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// <oprogram> is missing
|
||||
if (! prog_found)
|
||||
{
|
||||
ERR_CONTEXT(ret_syntax);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
// <oprogram> is missing
|
||||
if (!prog_found) {
|
||||
ERR_CONTEXT(ret_syntax);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check symbols number vs stack size
|
||||
if (stack_size() < count_symbols)
|
||||
{
|
||||
ERR_CONTEXT(ret_missing_operand);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
// check symbols number vs stack size
|
||||
if (stack_size() < count_symbols) {
|
||||
ERR_CONTEXT(ret_missing_operand);
|
||||
show_error(_err, context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// load variables
|
||||
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--)
|
||||
{
|
||||
_local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0));
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
// load variables
|
||||
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) {
|
||||
_local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0),
|
||||
_stack->get_len(0));
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
// run the program
|
||||
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
||||
program prog(this);
|
||||
// run the program
|
||||
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
||||
program prog(this);
|
||||
|
||||
// make the program from entry
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
// make the program from entry
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok) {
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
|
||||
// point on next command
|
||||
return myobj.arg1 + count_symbols + 2;
|
||||
// point on next command
|
||||
return myobj.arg1 + count_symbols + 2;
|
||||
}
|
||||
|
|
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)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
||||
(void)_stack->pop_back(2);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
_calc_stack.pop_back(2);
|
||||
|
||||
void rpn_swap(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||
(void)_stack->pop_back(2);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
void rpn_drop(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_drop(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
void rpn_drop2(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
(void)_stack->pop_back(2);
|
||||
}
|
||||
|
||||
void rpn_dropn(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args + 1);
|
||||
|
||||
(void)_stack->pop_back(args + 1);
|
||||
}
|
||||
|
||||
void rpn_erase(void) { (void)_stack->pop_back(_stack->size()); }
|
||||
|
||||
void rpn_dup(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack);
|
||||
}
|
||||
|
||||
void rpn_dup2(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||
}
|
||||
|
||||
void rpn_dupn(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args + 1);
|
||||
_stack->pop_back();
|
||||
|
||||
for (int i = 0; i < args; i++)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack);
|
||||
}
|
||||
|
||||
void rpn_pick(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
unsigned int to_pick =
|
||||
(unsigned int)int(((number*)_stack->pop_back())->_value);
|
||||
|
||||
// treat stack depth errors
|
||||
if ((to_pick == 0) || (to_pick > _stack->size())) {
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
return;
|
||||
}
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack);
|
||||
}
|
||||
|
||||
void rpn_rot(void) {
|
||||
MIN_ARGUMENTS(3);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
(void)_stack->pop_back(3);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack);
|
||||
_calc_stack.pop_back(3);
|
||||
}
|
||||
|
||||
void rpn_depth(void) {
|
||||
unsigned long depth = (unsigned long)_stack->size();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
num->set(depth);
|
||||
}
|
||||
|
||||
void rpn_roll(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args + 1);
|
||||
_stack->pop_back();
|
||||
|
||||
for (int i = 0; i < args; i++) {
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
for (int i = 1; i < args; i++)
|
||||
stack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, args - 1, *_stack);
|
||||
|
||||
_calc_stack.pop_back(args);
|
||||
}
|
||||
|
||||
void rpn_drop2(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
(void)_stack->pop_back(2);
|
||||
void rpn_rolld(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args + 1);
|
||||
_stack->pop_back();
|
||||
|
||||
for (int i = 0; i < args; i++) {
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack);
|
||||
|
||||
for (int i = 1; i < args; i++)
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack);
|
||||
|
||||
_calc_stack.pop_back(args);
|
||||
}
|
||||
|
||||
void rpn_dropn(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
void rpn_over(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args+1);
|
||||
|
||||
(void)_stack->pop_back(args+1);
|
||||
}
|
||||
|
||||
void rpn_erase(void)
|
||||
{
|
||||
(void)_stack->pop_back(_stack->size());
|
||||
}
|
||||
|
||||
void rpn_dup(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, *_stack);
|
||||
}
|
||||
|
||||
void rpn_dup2(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
||||
}
|
||||
|
||||
void rpn_dupn(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args+1);
|
||||
_stack->pop_back();
|
||||
|
||||
for (int i=0;i<args;i++)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-args, *_stack);
|
||||
}
|
||||
|
||||
void rpn_pick(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_back())->_value);
|
||||
|
||||
// treat stack depth errors
|
||||
if ((to_pick == 0) || (to_pick > _stack->size()))
|
||||
{
|
||||
ERR_CONTEXT(ret_out_of_range);
|
||||
return;
|
||||
}
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-to_pick, *_stack);
|
||||
}
|
||||
|
||||
void rpn_rot(void)
|
||||
{
|
||||
MIN_ARGUMENTS(3);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-3, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, _calc_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
(void)_stack->pop_back(3);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-2, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-3, *_stack);
|
||||
_calc_stack.pop_back(3);
|
||||
}
|
||||
|
||||
void rpn_depth(void)
|
||||
{
|
||||
unsigned long depth = (unsigned long)_stack->size();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
num->set(depth);
|
||||
}
|
||||
|
||||
void rpn_roll(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args+1);
|
||||
_stack->pop_back();
|
||||
|
||||
for(int i=0;i<args;i++)
|
||||
{
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
for(int i=1;i<args;i++)
|
||||
stack::copy_and_push_back(_calc_stack, args-1-i, *_stack);
|
||||
stack::copy_and_push_back(_calc_stack, args-1, *_stack);
|
||||
|
||||
_calc_stack.pop_back(args);
|
||||
}
|
||||
|
||||
void rpn_rolld(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
MIN_ARGUMENTS(args+1);
|
||||
_stack->pop_back();
|
||||
|
||||
for(int i=0;i<args;i++)
|
||||
{
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-args, *_stack);
|
||||
|
||||
for(int i=1;i<args;i++)
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-i, *_stack);
|
||||
|
||||
_calc_stack.pop_back(args);
|
||||
}
|
||||
|
||||
void rpn_over(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-2, *_stack);
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack);
|
||||
}
|
||||
|
|
|
@ -1,327 +1,273 @@
|
|||
//
|
||||
void rpn_sto(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
void rpn_sto(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
string name(((symbol*)_stack->pop_back())->_value);
|
||||
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
|
||||
(void)_stack->pop_back();
|
||||
string name(((symbol*)_stack->pop_back())->_value);
|
||||
_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
|
||||
(void)_stack->pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
void rpn_stoadd(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
void rpn_stoadd(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_plus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
||||
{
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
rpn_plus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stosub(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_minus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
||||
{
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
rpn_minus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stomul(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_mul();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
||||
{
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
rpn_mul();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stodiv(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_div();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number)
|
||||
{
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
rpn_div();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stoneg(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_neg();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stoinv(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol)
|
||||
{
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok)
|
||||
{
|
||||
rpn_inv();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_rcl(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
// recall a variable
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
|
||||
// mind the order of heaps
|
||||
if (find_variable(variable, obj, size))
|
||||
{
|
||||
(void)_stack->pop_back();
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_plus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||
_stack->get_type(0) == cmd_number) {
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
rpn_plus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_edit(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_stosub(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
FILE* tmp = tmpfile();
|
||||
if (tmp != NULL)
|
||||
{
|
||||
// re-write stack objet in a stream
|
||||
((object*)_stack->pop_back())->show(tmp);
|
||||
|
||||
// edit: stuff chars using readline facility
|
||||
int len = (int)ftell(tmp);
|
||||
rewind(tmp);
|
||||
|
||||
// get stream data
|
||||
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
|
||||
if (file_data != MAP_FAILED)
|
||||
{
|
||||
// set it as the linenoise line entry
|
||||
linenoisePreloadBuffer((const char*)file_data);
|
||||
munmap(file_data, len);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
|
||||
fclose(tmp);
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_minus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||
_stack->get_type(0) == cmd_number) {
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
rpn_minus();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stomul(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_mul();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||
_stack->get_type(0) == cmd_number) {
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
rpn_mul();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stodiv(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_div();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else if (_stack->get_type(1) == cmd_symbol &&
|
||||
_stack->get_type(0) == cmd_number) {
|
||||
// copy value, get variable value on stack level 1,
|
||||
// put back value on stack level 1, make op then modify variable
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
_stack->pop_back();
|
||||
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
rpn_div();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stoneg(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_neg();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_stoinv(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_symbol) {
|
||||
// get variable value on stack level 1, make op then modify variable
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
rpn_rcl();
|
||||
if (_err == ret_ok) {
|
||||
rpn_inv();
|
||||
_heap->add(variable, _stack->get_obj(0), _stack->get_len(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_rcl(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
// recall a variable
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
|
||||
// mind the order of heaps
|
||||
if (find_variable(variable, obj, size)) {
|
||||
(void)_stack->pop_back();
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
} else
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
|
||||
void rpn_edit(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
FILE* tmp = tmpfile();
|
||||
if (tmp != NULL) {
|
||||
// re-write stack objet in a stream
|
||||
((object*)_stack->pop_back())->show(tmp);
|
||||
|
||||
// edit: stuff chars using readline facility
|
||||
int len = (int)ftell(tmp);
|
||||
rewind(tmp);
|
||||
|
||||
// get stream data
|
||||
void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0);
|
||||
if (file_data != MAP_FAILED) {
|
||||
// set it as the linenoise line entry
|
||||
linenoisePreloadBuffer((const char*)file_data);
|
||||
munmap(file_data, len);
|
||||
} else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
|
||||
fclose(tmp);
|
||||
} else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
}
|
||||
|
||||
// carefull : this is not a langage command
|
||||
void auto_rcl(symbol* symb)
|
||||
{
|
||||
if (symb->_auto_eval)
|
||||
{
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
string variable(symb->_value);
|
||||
|
||||
// mind the order of heaps
|
||||
if (find_variable(variable, obj, size))
|
||||
{
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
if (obj->_type == cmd_program)
|
||||
rpn_eval();
|
||||
}
|
||||
else
|
||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||
}
|
||||
else
|
||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||
}
|
||||
|
||||
void rpn_purge(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
string name(((symbol*)_stack->pop_back())->_value);
|
||||
if (!_heap->erase(name))
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
|
||||
void rpn_vars(void)
|
||||
{
|
||||
void auto_rcl(symbol* symb) {
|
||||
if (symb->_auto_eval) {
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
program* parent = _parent_prog;
|
||||
string name;
|
||||
string variable(symb->_value);
|
||||
|
||||
// heap variables
|
||||
for (int i=0; i<(int)_heap->count_vars(); i++)
|
||||
{
|
||||
(void)_heap->get_by_index(i, name, obj, size);
|
||||
printf("var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// parents local variables
|
||||
while (parent != NULL)
|
||||
{
|
||||
for (int i=0; i<(int)parent->_local_heap.size(); i++)
|
||||
{
|
||||
(void)parent->_local_heap.get_by_index(i, name, obj, size);
|
||||
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
parent = parent->_parent_prog;
|
||||
}
|
||||
|
||||
// local variables
|
||||
for (int i=0; i<(int)_local_heap.size(); i++)
|
||||
{
|
||||
(void)_local_heap.get_by_index(i, name, obj, size);
|
||||
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
// mind the order of heaps
|
||||
if (find_variable(variable, obj, size)) {
|
||||
stack::copy_and_push_back(obj, *_stack, size);
|
||||
if (obj->_type == cmd_program) rpn_eval();
|
||||
} else
|
||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||
} else
|
||||
stack::copy_and_push_back(symb, *_stack, symb->size());
|
||||
}
|
||||
|
||||
void rpn_clusr(void)
|
||||
{
|
||||
_heap->erase_all();
|
||||
void rpn_purge(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
string name(((symbol*)_stack->pop_back())->_value);
|
||||
if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
|
||||
void rpn_vars(void) {
|
||||
object* obj;
|
||||
unsigned int size;
|
||||
program* parent = _parent_prog;
|
||||
string name;
|
||||
|
||||
// heap variables
|
||||
for (int i = 0; i < (int)_heap->count_vars(); i++) {
|
||||
(void)_heap->get_by_index(i, name, obj, size);
|
||||
printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||
object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// parents local variables
|
||||
while (parent != NULL) {
|
||||
for (int i = 0; i < (int)parent->_local_heap.size(); i++) {
|
||||
(void)parent->_local_heap.get_by_index(i, name, obj, size);
|
||||
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||
object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
parent = parent->_parent_prog;
|
||||
}
|
||||
|
||||
// local variables
|
||||
for (int i = 0; i < (int)_local_heap.size(); i++) {
|
||||
(void)_local_heap.get_by_index(i, name, obj, size);
|
||||
printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(),
|
||||
object::s_cmd_type_string[obj->_type]);
|
||||
obj->show();
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_clusr(void) { _heap->erase_all(); }
|
||||
|
|
|
@ -1,152 +1,140 @@
|
|||
void rpn_instr()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_instr() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
// stringify only if not already a string
|
||||
if (_stack->get_type(0) != cmd_string)
|
||||
{
|
||||
// write the object in stack(0) in a string and remove this obj
|
||||
FILE* tmp = tmpfile();
|
||||
if (tmp != NULL)
|
||||
{
|
||||
((object*)_stack->pop_back())->show(tmp);
|
||||
// stringify only if not already a string
|
||||
if (_stack->get_type(0) != cmd_string) {
|
||||
// write the object in stack(0) in a string and remove this obj
|
||||
FILE* tmp = tmpfile();
|
||||
if (tmp != NULL) {
|
||||
((object*)_stack->pop_back())->show(tmp);
|
||||
|
||||
// reserve the correct size on stack
|
||||
unsigned int str_size = (unsigned int)ftell(tmp);
|
||||
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
||||
str->_len = str_size;
|
||||
// reserve the correct size on stack
|
||||
unsigned int str_size = (unsigned int)ftell(tmp);
|
||||
ostring* str = (ostring*)_stack->allocate_back(
|
||||
str_size + 1 + sizeof(ostring), cmd_string);
|
||||
str->_len = str_size;
|
||||
|
||||
// fill the obj
|
||||
rewind(tmp);
|
||||
if (fread(str->_value, str_size, 1, tmp) != 1)
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
str->_value[str_size] = 0;
|
||||
fclose(tmp);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
}
|
||||
// fill the obj
|
||||
rewind(tmp);
|
||||
if (fread(str->_value, str_size, 1, tmp) != 1)
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
str->_value[str_size] = 0;
|
||||
fclose(tmp);
|
||||
} else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_strout()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
void rpn_strout() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
string entry(((ostring*)_stack->pop_back())->_value);
|
||||
string entry(((ostring*)_stack->pop_back())->_value);
|
||||
|
||||
program prog;
|
||||
program prog;
|
||||
|
||||
// make program from string in stack level 1
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
// make program from string in stack level 1
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
|
||||
void rpn_chr()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
void rpn_chr() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
// get arg as number % 256
|
||||
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
|
||||
if (the_chr<32 || the_chr>126)
|
||||
the_chr = '.';
|
||||
// get arg as number % 256
|
||||
char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr,
|
||||
floating_t::s_mpfr_rnd);
|
||||
if (the_chr < 32 || the_chr > 126) the_chr = '.';
|
||||
|
||||
// reserve the correct size on stack (1 char)
|
||||
unsigned int str_size = 1;
|
||||
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
||||
// reserve the correct size on stack (1 char)
|
||||
unsigned int str_size = 1;
|
||||
ostring* str = (ostring*)_stack->allocate_back(str_size + 1 + sizeof(ostring),
|
||||
cmd_string);
|
||||
str->_len = str_size;
|
||||
str->_value[0] = the_chr;
|
||||
str->_value[1] = 0;
|
||||
}
|
||||
|
||||
void rpn_num() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0];
|
||||
number* numb =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = the_chr;
|
||||
}
|
||||
|
||||
void rpn_strsize() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
double len = ((ostring*)_stack->pop_back())->_len;
|
||||
number* numb =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = len;
|
||||
}
|
||||
|
||||
void rpn_strpos() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||
|
||||
long pos = 0;
|
||||
char* src = ((ostring*)_stack->get_obj(1))->_value;
|
||||
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
|
||||
if (found != NULL) pos = (long)(found - src) + 1L;
|
||||
|
||||
_stack->pop_back(2);
|
||||
|
||||
number* numb =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = pos;
|
||||
}
|
||||
|
||||
void rpn_strsub() {
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(2, cmd_string);
|
||||
|
||||
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
|
||||
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
|
||||
long len = ((ostring*)_stack->get_obj(2))->_len;
|
||||
bool result_is_void = false;
|
||||
|
||||
_stack->pop_back(2);
|
||||
|
||||
if (first < 0) first = 0;
|
||||
if (last < 0) last = 0;
|
||||
if (first > len && last > len)
|
||||
result_is_void = true;
|
||||
else {
|
||||
if (first > len) first = len - 1;
|
||||
if (last > len) last = len - 1;
|
||||
if (first > last) result_is_void = true;
|
||||
}
|
||||
|
||||
if (!result_is_void) {
|
||||
unsigned int str_size = last - first + 1;
|
||||
ostring* str = (ostring*)_calc_stack.allocate_back(
|
||||
str_size + 1 + sizeof(ostring), cmd_string);
|
||||
str->_len = str_size;
|
||||
str->_value[0] = the_chr;
|
||||
str->_value[1] = 0;
|
||||
}
|
||||
|
||||
void rpn_num()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
double the_chr = (double)((ostring*)_stack->pop_back())->_value[0];
|
||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = the_chr;
|
||||
}
|
||||
|
||||
void rpn_strsize()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
double len = ((ostring*)_stack->pop_back())->_len;
|
||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = len;
|
||||
}
|
||||
|
||||
void rpn_strpos()
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||
|
||||
long pos = 0;
|
||||
char* src = ((ostring*)_stack->get_obj(1))->_value;
|
||||
char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value);
|
||||
if (found != NULL)
|
||||
pos = (long)(found - src)+1L;
|
||||
|
||||
_stack->pop_back(2);
|
||||
|
||||
number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
numb->_value = pos;
|
||||
}
|
||||
|
||||
void rpn_strsub()
|
||||
{
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(2, cmd_string);
|
||||
|
||||
long first = long(((number*)_stack->get_obj(1))->_value) - 1;
|
||||
long last = long(((number*)_stack->get_obj(0))->_value) - 1;
|
||||
long len = ((ostring*)_stack->get_obj(2))->_len;
|
||||
bool result_is_void = false;
|
||||
|
||||
_stack->pop_back(2);
|
||||
|
||||
if (first < 0)
|
||||
first = 0;
|
||||
if (last < 0)
|
||||
last = 0;
|
||||
if (first > len && last > len)
|
||||
result_is_void=true;
|
||||
else
|
||||
{
|
||||
if (first > len)
|
||||
first = len -1;
|
||||
if (last > len)
|
||||
last = len -1;
|
||||
if (first > last)
|
||||
result_is_void=true;
|
||||
}
|
||||
|
||||
if (!result_is_void)
|
||||
{
|
||||
unsigned int str_size = last - first + 1;
|
||||
ostring* str = (ostring*)_calc_stack.allocate_back(str_size+1+sizeof(ostring), cmd_string);
|
||||
str->_len = str_size;
|
||||
|
||||
memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->get_obj(0))->_value+first, str_size);
|
||||
((ostring*)_calc_stack.back())->_value[str_size] = 0;
|
||||
|
||||
_stack->pop_back();
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size()-1, *_stack);
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
_stack->pop_back();
|
||||
ostring* str = (ostring*)_stack->allocate_back(1+sizeof(ostring), cmd_string);
|
||||
str->_len = 0;
|
||||
str->_value[0] = 0;
|
||||
}
|
||||
|
||||
memcpy(((ostring*)_calc_stack.back())->_value,
|
||||
((ostring*)_stack->get_obj(0))->_value + first, str_size);
|
||||
((ostring*)_calc_stack.back())->_value[str_size] = 0;
|
||||
|
||||
_stack->pop_back();
|
||||
stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack);
|
||||
_calc_stack.pop_back();
|
||||
} else {
|
||||
_stack->pop_back();
|
||||
ostring* str =
|
||||
(ostring*)_stack->allocate_back(1 + sizeof(ostring), cmd_string);
|
||||
str->_len = 0;
|
||||
str->_value[0] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,251 +1,223 @@
|
|||
void test_get_stack(string& stack_is, stack& stk)
|
||||
{
|
||||
// write stack in a string, each entry separated between commas
|
||||
for (int i = 0; i < (int)stk.size(); i++)
|
||||
{
|
||||
FILE* tmp_file = tmpfile();
|
||||
char* line = NULL;
|
||||
size_t len;
|
||||
void test_get_stack(string& stack_is, stack& stk) {
|
||||
// write stack in a string, each entry separated between commas
|
||||
for (int i = 0; i < (int)stk.size(); i++) {
|
||||
FILE* tmp_file = tmpfile();
|
||||
char* line = NULL;
|
||||
size_t len;
|
||||
|
||||
if (i > 0)
|
||||
stack_is += ", ";
|
||||
if (i > 0) stack_is += ", ";
|
||||
|
||||
if (tmp_file != NULL)
|
||||
{
|
||||
((object*)stk.seq_obj(i))->show(tmp_file);
|
||||
if (tmp_file != NULL) {
|
||||
((object*)stk.seq_obj(i))->show(tmp_file);
|
||||
|
||||
// write stack in a tmp file
|
||||
(void)rewind(tmp_file);
|
||||
if (getline(&line, &len, tmp_file) >=0)
|
||||
{
|
||||
stack_is += line;
|
||||
free(line);
|
||||
}
|
||||
(void)fclose(tmp_file);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
}
|
||||
// write stack in a tmp file
|
||||
(void)rewind(tmp_file);
|
||||
if (getline(&line, &len, tmp_file) >= 0) {
|
||||
stack_is += line;
|
||||
free(line);
|
||||
}
|
||||
(void)fclose(tmp_file);
|
||||
} else
|
||||
ERR_CONTEXT(ret_runtime_error);
|
||||
}
|
||||
}
|
||||
|
||||
void test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed)
|
||||
{
|
||||
printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests-tests_failed);
|
||||
if(tests_failed>0)
|
||||
printf(FG_RED);
|
||||
printf("%d failed", tests_failed);
|
||||
if(tests_failed>0)
|
||||
printf(COLOR_OFF);
|
||||
void test_show_result(string title, int tests, int tests_failed, int steps,
|
||||
int steps_failed) {
|
||||
printf("%s: run %d tests: %d passed, ", title.c_str(), tests,
|
||||
tests - tests_failed);
|
||||
if (tests_failed > 0) printf(FG_RED);
|
||||
printf("%d failed", tests_failed);
|
||||
if (tests_failed > 0) printf(COLOR_OFF);
|
||||
|
||||
printf(" (%d steps: %d passed, ", steps, steps-steps_failed);
|
||||
if(steps_failed>0)
|
||||
printf(FG_RED);
|
||||
printf("%d failed", steps_failed);
|
||||
if(steps_failed>0)
|
||||
printf(COLOR_OFF);
|
||||
printf(")\n");
|
||||
printf(" (%d steps: %d passed, ", steps, steps - steps_failed);
|
||||
if (steps_failed > 0) printf(FG_RED);
|
||||
printf("%d failed", steps_failed);
|
||||
if (steps_failed > 0) printf(COLOR_OFF);
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void rpn_test()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
void rpn_test() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
int total_tests=0;
|
||||
int total_tests_failed=0;
|
||||
int total_steps=0;
|
||||
int total_steps_failed=0;
|
||||
int total_tests = 0;
|
||||
int total_tests_failed = 0;
|
||||
int total_steps = 0;
|
||||
int total_steps_failed = 0;
|
||||
|
||||
string test_filename = ((ostring*)_stack->pop_back())->_value;
|
||||
printf("\nrpn version is %s\n", version);
|
||||
test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed);
|
||||
test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed);
|
||||
string test_filename = ((ostring*)_stack->pop_back())->_value;
|
||||
printf("\nrpn version is %s\n", version);
|
||||
test(test_filename, total_tests, total_tests_failed, total_steps,
|
||||
total_steps_failed);
|
||||
test_show_result("Total", total_tests, total_tests_failed, total_steps,
|
||||
total_steps_failed);
|
||||
}
|
||||
|
||||
void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed)
|
||||
{
|
||||
const string stack_size("-> stack size should be ");
|
||||
const string stack_value("-> stack should be ");
|
||||
const string cmd_error("-> error should be ");
|
||||
const string cmd_exit("exit test");
|
||||
void test(string test_filename, int& total_tests, int& total_tests_failed,
|
||||
int& total_steps, int& total_steps_failed) {
|
||||
const string stack_size("-> stack size should be ");
|
||||
const string stack_value("-> stack should be ");
|
||||
const string cmd_error("-> error should be ");
|
||||
const string cmd_exit("exit test");
|
||||
|
||||
ifstream test_file(test_filename.c_str());
|
||||
int tests = 0;
|
||||
int tests_failed = 0;
|
||||
int steps = 0;
|
||||
int steps_failed = 0;
|
||||
ifstream test_file(test_filename.c_str());
|
||||
int tests = 0;
|
||||
int tests_failed = 0;
|
||||
int steps = 0;
|
||||
int steps_failed = 0;
|
||||
|
||||
if (test_file.is_open())
|
||||
{
|
||||
string test_title;
|
||||
string entry;
|
||||
ret_value ret;
|
||||
stack stk;
|
||||
heap hp;
|
||||
bool failed = false;
|
||||
bool is_first_step;
|
||||
bool is_test_error_shown;
|
||||
int last_err;
|
||||
stringstream cerr_buffer;
|
||||
streambuf* cerr_old_buffer;
|
||||
if (test_file.is_open()) {
|
||||
string test_title;
|
||||
string entry;
|
||||
ret_value ret;
|
||||
stack stk;
|
||||
heap hp;
|
||||
bool failed = false;
|
||||
bool is_first_step;
|
||||
bool is_test_error_shown;
|
||||
int last_err;
|
||||
stringstream cerr_buffer;
|
||||
streambuf* cerr_old_buffer;
|
||||
|
||||
// redirect cerr
|
||||
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
|
||||
// redirect cerr
|
||||
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
|
||||
|
||||
while (!test_file.eof())
|
||||
{
|
||||
getline(test_file, entry);
|
||||
while (!test_file.eof()) {
|
||||
getline(test_file, entry);
|
||||
|
||||
if (entry.substr(0,8)=="#include")
|
||||
test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed);
|
||||
else if (entry.substr(0,2)=="##")
|
||||
printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str());
|
||||
else if (entry.substr(0,2)=="# ")
|
||||
{
|
||||
// indicates the status of previous test
|
||||
if (failed == false && tests > 0)
|
||||
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||
failed = false;
|
||||
|
||||
// read a test title
|
||||
test_title = entry;
|
||||
is_first_step = true;
|
||||
is_test_error_shown = false;
|
||||
printf("%s", test_title.c_str());
|
||||
}
|
||||
// treat "-> stack size should be "
|
||||
else if (entry.find(stack_size, 0) == 0)
|
||||
{
|
||||
// count test and step
|
||||
if (is_first_step)
|
||||
tests++;
|
||||
steps++;
|
||||
|
||||
// check current stack size
|
||||
istringstream isub;
|
||||
int size;
|
||||
|
||||
isub.str(entry.substr(stack_size.size()));
|
||||
isub>>size;
|
||||
if (size != (int)stk.size())
|
||||
{
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown)
|
||||
{
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n", stk.size());
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
}
|
||||
// treat "-> stack should be "
|
||||
else if (entry.find(stack_value, 0) == 0)
|
||||
{
|
||||
// count test
|
||||
if (is_first_step)
|
||||
tests++;
|
||||
steps++;
|
||||
|
||||
// check current stack value
|
||||
string stack_should_be = entry.substr(stack_value.size());
|
||||
string stack_is;
|
||||
|
||||
test_get_stack(stack_is, stk);
|
||||
|
||||
if (stack_is != stack_should_be)
|
||||
{
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown)
|
||||
{
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n", stack_is.c_str());
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
}
|
||||
// treat "-> error should be "
|
||||
else if (entry.find(cmd_error, 0) == 0)
|
||||
{
|
||||
// count test
|
||||
if (is_first_step)
|
||||
tests++;
|
||||
steps++;
|
||||
|
||||
// check current error
|
||||
istringstream isub;
|
||||
int err_should_be;
|
||||
isub.str(entry.substr(cmd_error.size()));
|
||||
isub>>err_should_be;
|
||||
if (err_should_be != last_err)
|
||||
{
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown)
|
||||
{
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
}
|
||||
else if (entry.find(cmd_exit, 0) == 0)
|
||||
{
|
||||
// forced test end
|
||||
break;
|
||||
}
|
||||
else if (entry.size() > 0)
|
||||
{
|
||||
// parse entry and run line
|
||||
program prog;
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
// run it
|
||||
(void)prog.run(stk, hp);
|
||||
last_err = (int)prog.get_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last test
|
||||
if (entry.substr(0, 8) == "#include")
|
||||
test(entry.substr(9), total_tests, total_tests_failed, total_steps,
|
||||
total_steps_failed);
|
||||
else if (entry.substr(0, 2) == "##")
|
||||
printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str());
|
||||
else if (entry.substr(0, 2) == "# ") {
|
||||
// indicates the status of previous test
|
||||
if (failed == false && tests > 0)
|
||||
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||
printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||
failed = false;
|
||||
|
||||
// cerr back
|
||||
cerr.rdbuf(cerr_old_buffer);
|
||||
// read a test title
|
||||
test_title = entry;
|
||||
is_first_step = true;
|
||||
is_test_error_shown = false;
|
||||
printf("%s", test_title.c_str());
|
||||
}
|
||||
// treat "-> stack size should be "
|
||||
else if (entry.find(stack_size, 0) == 0) {
|
||||
// count test and step
|
||||
if (is_first_step) tests++;
|
||||
steps++;
|
||||
|
||||
// conclusion: show and keep for total
|
||||
if (tests != 0)
|
||||
{
|
||||
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
|
||||
// check current stack size
|
||||
istringstream isub;
|
||||
int size;
|
||||
|
||||
total_tests += tests;
|
||||
total_tests_failed += tests_failed;
|
||||
total_steps += steps;
|
||||
total_steps_failed += steps_failed;
|
||||
isub.str(entry.substr(stack_size.size()));
|
||||
isub >> size;
|
||||
if (size != (int)stk.size()) {
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown) {
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n",
|
||||
stk.size());
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
}
|
||||
// treat "-> stack should be "
|
||||
else if (entry.find(stack_value, 0) == 0) {
|
||||
// count test
|
||||
if (is_first_step) tests++;
|
||||
steps++;
|
||||
|
||||
// check current stack value
|
||||
string stack_should_be = entry.substr(stack_value.size());
|
||||
string stack_is;
|
||||
|
||||
test_get_stack(stack_is, stk);
|
||||
|
||||
if (stack_is != stack_should_be) {
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown) {
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n",
|
||||
stack_is.c_str());
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
}
|
||||
// treat "-> error should be "
|
||||
else if (entry.find(cmd_error, 0) == 0) {
|
||||
// count test
|
||||
if (is_first_step) tests++;
|
||||
steps++;
|
||||
|
||||
// check current error
|
||||
istringstream isub;
|
||||
int err_should_be;
|
||||
isub.str(entry.substr(cmd_error.size()));
|
||||
isub >> err_should_be;
|
||||
if (err_should_be != last_err) {
|
||||
// count fail test and step
|
||||
if (!is_test_error_shown) {
|
||||
printf(FG_RED " FAIL" COLOR_OFF "\n");
|
||||
tests_failed++;
|
||||
is_test_error_shown = true;
|
||||
}
|
||||
steps_failed++;
|
||||
|
||||
// show failure
|
||||
printf("\t%s\n", entry.c_str());
|
||||
printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err);
|
||||
failed = true;
|
||||
}
|
||||
is_first_step = false;
|
||||
} else if (entry.find(cmd_exit, 0) == 0) {
|
||||
// forced test end
|
||||
break;
|
||||
} else if (entry.size() > 0) {
|
||||
// parse entry and run line
|
||||
program prog;
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok) {
|
||||
// run it
|
||||
(void)prog.run(stk, hp);
|
||||
last_err = (int)prog.get_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str());
|
||||
|
||||
// last test
|
||||
// indicates the status of previous test
|
||||
if (failed == false && tests > 0) printf(FG_GREEN " PASSED" COLOR_OFF "\n");
|
||||
|
||||
// cerr back
|
||||
cerr.rdbuf(cerr_old_buffer);
|
||||
|
||||
// conclusion: show and keep for total
|
||||
if (tests != 0) {
|
||||
test_show_result(test_filename, tests, tests_failed, steps, steps_failed);
|
||||
|
||||
total_tests += tests;
|
||||
total_tests_failed += tests_failed;
|
||||
total_steps += steps;
|
||||
total_steps_failed += steps_failed;
|
||||
}
|
||||
} else
|
||||
fprintf(stderr, "test file '%s' not found\n", test_filename.c_str());
|
||||
}
|
||||
|
|
469
src/rpn-test.hpp
469
src/rpn-test.hpp
|
@ -1,270 +1,251 @@
|
|||
int cmp_strings_on_stack_top()
|
||||
{
|
||||
// _stack sould have 2 strings at level 1 and 2
|
||||
// this function removes these 2 entries
|
||||
ostring* right = (ostring*)_stack->pop_back();
|
||||
ostring* left = (ostring*)_stack->pop_back();
|
||||
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
|
||||
int cmp_strings_on_stack_top() {
|
||||
// _stack sould have 2 strings at level 1 and 2
|
||||
// this function removes these 2 entries
|
||||
ostring* right = (ostring*)_stack->pop_back();
|
||||
ostring* left = (ostring*)_stack->pop_back();
|
||||
return strncmp(left->_value, right->_value, min(left->_len, right->_len));
|
||||
}
|
||||
|
||||
void rpn_sup(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
void rpn_sup(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp > 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_sup_eq(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp >= 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_inf(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp < 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_inf_eq(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp <= 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_diff(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// complexes
|
||||
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
|
||||
{
|
||||
bool diff = false;
|
||||
complex* right = (complex*)_stack->pop_back();
|
||||
complex* left = (complex*)_stack->pop_back();
|
||||
|
||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||
diff = true;
|
||||
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
if (diff)
|
||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp != 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_eq(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number)
|
||||
{
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// complexes
|
||||
else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex)
|
||||
{
|
||||
bool diff = false;
|
||||
complex* right = (complex*)_stack->pop_back();
|
||||
complex* left = (complex*)_stack->pop_back();
|
||||
|
||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||
diff = true;
|
||||
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
if (diff)
|
||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string)
|
||||
{
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp == 0) ? 1L : 0L;
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_test_and(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
|
||||
&& (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp > 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_test_or(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
void rpn_sup_eq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
|
||||
|| (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp >= 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_test_xor(void)
|
||||
{
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
void rpn_inf(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
||||
{
|
||||
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
{
|
||||
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp < 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_test_not(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
void rpn_inf_eq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp <= 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_same(void)
|
||||
{
|
||||
rpn_eq();
|
||||
void rpn_diff(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// complexes
|
||||
else if (_stack->get_type(0) == cmd_complex &&
|
||||
_stack->get_type(1) == cmd_complex) {
|
||||
bool diff = false;
|
||||
complex* right = (complex*)_stack->pop_back();
|
||||
complex* left = (complex*)_stack->pop_back();
|
||||
|
||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
|
||||
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||
diff = true;
|
||||
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
if (diff)
|
||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp != 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_eq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
// numbers
|
||||
if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) {
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// complexes
|
||||
else if (_stack->get_type(0) == cmd_complex &&
|
||||
_stack->get_type(1) == cmd_complex) {
|
||||
bool diff = false;
|
||||
complex* right = (complex*)_stack->pop_back();
|
||||
complex* left = (complex*)_stack->pop_back();
|
||||
|
||||
if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 ||
|
||||
mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0)
|
||||
diff = true;
|
||||
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
if (diff)
|
||||
mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
// strings
|
||||
else if (_stack->get_type(0) == cmd_string &&
|
||||
_stack->get_type(1) == cmd_string) {
|
||||
int res_cmp = cmp_strings_on_stack_top();
|
||||
number* res =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
res->_value = (res_cmp == 0) ? 1L : 0L;
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_test_and(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) &&
|
||||
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
|
||||
void rpn_test_or(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) ||
|
||||
(mpfr_cmp_si(right->_value.mpfr, 0) != 0))
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
|
||||
void rpn_test_xor(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
||||
|
||||
number* right = (number*)_stack->pop_back();
|
||||
number* left = (number*)_stack->back();
|
||||
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0) {
|
||||
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
} else {
|
||||
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_test_not(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
number* left = (number*)_stack->back();
|
||||
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
|
||||
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
|
||||
else
|
||||
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
|
||||
}
|
||||
|
||||
void rpn_same(void) { rpn_eq(); }
|
||||
|
|
444
src/rpn-trig.hpp
444
src/rpn-trig.hpp
|
@ -1,263 +1,239 @@
|
|||
//
|
||||
void rpn_pi(void)
|
||||
{
|
||||
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
void rpn_pi(void) {
|
||||
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
||||
void rpn_d2r(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
void rpn_d2r(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
// add pi on stack
|
||||
rpn_pi();
|
||||
// add pi on stack
|
||||
rpn_pi();
|
||||
|
||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
|
||||
CHECK_MPFR(
|
||||
mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
||||
void rpn_r2d(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
// add pi on stack
|
||||
rpn_pi();
|
||||
|
||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
|
||||
CHECK_MPFR(
|
||||
mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
|
||||
void rpn_sin(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
|
||||
CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* tmp =
|
||||
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||
->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_r2d(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
void rpn_asin(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
// add pi on stack
|
||||
rpn_pi();
|
||||
|
||||
floating_t* pi = &((number*)_stack->pop_back())->_value;
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
|
||||
CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
number* num;
|
||||
complex* i;
|
||||
|
||||
// asin(z)=-iln(iz+sqrt(1-z*z))
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
i = (complex*)_calc_stack.get_obj(0);
|
||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
|
||||
rpn_dup();
|
||||
rpn_square();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
rpn_squareroot();
|
||||
rpn_swap();
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
rpn_neg();
|
||||
_calc_stack.pop_back();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_sin(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_cos(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
|
||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
floating_t* tmp =
|
||||
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||
->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_asin(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_acos(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
number* num;
|
||||
complex* i;
|
||||
|
||||
//asin(z)=-iln(iz+sqrt(1-z*z))
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
|
||||
i = (complex*)_calc_stack.get_obj(0);
|
||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
|
||||
rpn_dup();
|
||||
rpn_square();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
rpn_squareroot();
|
||||
rpn_swap();
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
rpn_plus();
|
||||
rpn_ln();
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
rpn_neg();
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// acos(z)=pi/2-asin(z)
|
||||
rpn_asin();
|
||||
rpn_pi();
|
||||
number* num =
|
||||
(number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_div();
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_cos(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_tan(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
|
||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
// tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
floating_t* tmp =
|
||||
&((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))
|
||||
->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd));
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
// x->2x
|
||||
CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||
// y->2y
|
||||
CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||
|
||||
// sin(2x)+sinh(2y)
|
||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
// cosh(2y)+cos(2x)
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
// sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
|
||||
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_acos(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
void rpn_atan(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
//acos(z)=pi/2-asin(z)
|
||||
rpn_asin();
|
||||
rpn_pi();
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_div();
|
||||
rpn_minus();
|
||||
rpn_neg();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_tan(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
// tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x)
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
|
||||
floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value;
|
||||
floating_t* x = ((complex*)_calc_stack.get_obj(1))->re();
|
||||
floating_t* y = ((complex*)_calc_stack.get_obj(1))->im();
|
||||
|
||||
floating_t* re = ((complex*)_stack->get_obj(0))->re();
|
||||
floating_t* im = ((complex*)_stack->get_obj(0))->im();
|
||||
|
||||
//x->2x
|
||||
CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||
//y->2y
|
||||
CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd));
|
||||
|
||||
//sin(2x)+sinh(2y)
|
||||
CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
//cosh(2y)+cos(2x)
|
||||
CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
//sin(2x)+sinh(2y) / (cosh(2y)+cos(2x))
|
||||
CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd));
|
||||
|
||||
_calc_stack.pop_back(2);
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
||||
void rpn_atan(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
if (_stack->get_type(0) == cmd_number)
|
||||
{
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
}
|
||||
else if (_stack->get_type(0) == cmd_complex)
|
||||
{
|
||||
number* num;
|
||||
complex* i;
|
||||
|
||||
//atan(z)=0.5i(ln((1-iz)/(1+iz))
|
||||
stack::copy_and_push_back(*_stack, _stack->size()-1, _calc_stack);
|
||||
|
||||
i = (complex*)_calc_stack.get_obj(0);
|
||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus();//iz-1
|
||||
rpn_neg();//1-iz
|
||||
rpn_dup();
|
||||
rpn_neg();//iz-1
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus();//iz+1
|
||||
rpn_div();
|
||||
|
||||
rpn_ln();
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
|
||||
_calc_stack.pop_back();
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
if (_stack->get_type(0) == cmd_number) {
|
||||
floating_t* left = &((number*)_stack->get_obj(0))->_value;
|
||||
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
|
||||
} else if (_stack->get_type(0) == cmd_complex) {
|
||||
number* num;
|
||||
complex* i;
|
||||
|
||||
// atan(z)=0.5i(ln((1-iz)/(1+iz))
|
||||
stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack);
|
||||
|
||||
i = (complex*)_calc_stack.get_obj(0);
|
||||
CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd));
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd));
|
||||
rpn_minus(); // iz-1
|
||||
rpn_neg(); // 1-iz
|
||||
rpn_dup();
|
||||
rpn_neg(); // iz-1
|
||||
num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd));
|
||||
rpn_plus(); // iz+1
|
||||
rpn_div();
|
||||
|
||||
rpn_ln();
|
||||
CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd));
|
||||
stack::copy_and_push_back(_calc_stack, 0, *_stack);
|
||||
rpn_mul();
|
||||
|
||||
_calc_stack.pop_back();
|
||||
} else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
|
513
src/stack.hpp
513
src/stack.hpp
|
@ -6,326 +6,281 @@
|
|||
using namespace std;
|
||||
|
||||
// allocation base size
|
||||
#define ALLOC_STACK_CHUNK (64*1024)
|
||||
#define ALLOC_STACK_CHUNK (64 * 1024)
|
||||
|
||||
//
|
||||
class stack
|
||||
{
|
||||
public:
|
||||
stack()
|
||||
{
|
||||
_base = NULL;
|
||||
_base_pointer = NULL;
|
||||
_total_size = 0;
|
||||
_total_count_pointer = 0;
|
||||
erase();
|
||||
class stack {
|
||||
public:
|
||||
stack() {
|
||||
_base = NULL;
|
||||
_base_pointer = NULL;
|
||||
_total_size = 0;
|
||||
_total_count_pointer = 0;
|
||||
erase();
|
||||
}
|
||||
|
||||
virtual ~stack() {
|
||||
if (_base != NULL) free(_base);
|
||||
if (_base_pointer != NULL) free(_base_pointer);
|
||||
}
|
||||
|
||||
void erase() {
|
||||
_current = _base;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
//
|
||||
static void copy_and_push_back(stack& from, unsigned int index_from,
|
||||
stack& to) {
|
||||
// copy a whole stack entry and push it back to another stack
|
||||
object* allocated =
|
||||
to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
|
||||
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
|
||||
|
||||
if (allocated->_type == cmd_number)
|
||||
((number*)allocated)->move();
|
||||
else if (allocated->_type == cmd_complex)
|
||||
((complex*)allocated)->move();
|
||||
}
|
||||
|
||||
//
|
||||
static void copy_and_push_back(object* from, stack& to, unsigned int size) {
|
||||
// copy a whole stack entry and push it back to another stack
|
||||
object* allocated = to.allocate_back(size, from->_type);
|
||||
memcpy(allocated, from, size);
|
||||
|
||||
if (allocated->_type == cmd_number)
|
||||
((number*)allocated)->move();
|
||||
else if (allocated->_type == cmd_complex)
|
||||
((complex*)allocated)->move();
|
||||
}
|
||||
|
||||
object* allocate_back(unsigned int size, cmd_type_t type) {
|
||||
object* allocated;
|
||||
bool data_is_reallocated = false;
|
||||
char* old_base;
|
||||
|
||||
// manage data memory allocation (add as much as memory it is needed)
|
||||
if (((_current - _base) + size) > _total_size) {
|
||||
// calc nb of needed pages
|
||||
unsigned long page_number =
|
||||
1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
|
||||
_total_size += page_number * ALLOC_STACK_CHUNK;
|
||||
|
||||
old_base = _base;
|
||||
_base = (char*)realloc(_base, _total_size);
|
||||
|
||||
_current = _base + (_current - old_base);
|
||||
data_is_reallocated = true;
|
||||
}
|
||||
|
||||
virtual ~stack()
|
||||
{
|
||||
if (_base != NULL)
|
||||
free(_base);
|
||||
if (_base_pointer != NULL)
|
||||
free(_base_pointer);
|
||||
// manage pointers memory allocation (add one page if needed)
|
||||
if ((_count + 1) > _total_count_pointer) {
|
||||
_base_pointer = (object**)realloc(
|
||||
_base_pointer,
|
||||
(_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
|
||||
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
_current = _base;
|
||||
_count = 0;
|
||||
// recalc object pointers in case of base reallocation
|
||||
if (data_is_reallocated) {
|
||||
for (int i = 0; i < _count; i++) {
|
||||
_base_pointer[i] =
|
||||
(object*)(_base + ((char*)_base_pointer[i] - old_base));
|
||||
if (_base_pointer[i]->_type == cmd_number)
|
||||
((number*)_base_pointer[i])->move();
|
||||
else if (_base_pointer[i]->_type == cmd_complex)
|
||||
((complex*)_base_pointer[i])->move();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to)
|
||||
{
|
||||
// copy a whole stack entry and push it back to another stack
|
||||
object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
|
||||
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
|
||||
// manage stack itself
|
||||
_base_pointer[_count++] = (object*)_current;
|
||||
allocated = (object*)_current;
|
||||
_current += size;
|
||||
|
||||
if (allocated->_type == cmd_number)
|
||||
((number*)allocated)->move();
|
||||
else if (allocated->_type == cmd_complex)
|
||||
((complex*)allocated)->move();
|
||||
// init object
|
||||
allocated->_type = type;
|
||||
allocated->_size = size;
|
||||
if (type == cmd_number)
|
||||
((number*)allocated)->init();
|
||||
else if (type == cmd_complex)
|
||||
((complex*)allocated)->init();
|
||||
|
||||
return allocated;
|
||||
}
|
||||
|
||||
object* pop_back(int pop_count = 1) {
|
||||
object* back = NULL;
|
||||
|
||||
// pop several entries, return the last
|
||||
while (pop_count-- > 0) {
|
||||
if (_count > 0) {
|
||||
_current = (char*)_base_pointer[--_count];
|
||||
back = (object*)_current;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static void copy_and_push_back(object* from, stack& to, unsigned int size)
|
||||
{
|
||||
// copy a whole stack entry and push it back to another stack
|
||||
object* allocated = to.allocate_back(size, from->_type);
|
||||
memcpy(allocated, from, size);
|
||||
return back;
|
||||
}
|
||||
|
||||
if (allocated->_type == cmd_number)
|
||||
((number*)allocated)->move();
|
||||
else if (allocated->_type == cmd_complex)
|
||||
((complex*)allocated)->move();
|
||||
}
|
||||
|
||||
object* allocate_back(unsigned int size, cmd_type_t type)
|
||||
{
|
||||
object* allocated;
|
||||
bool data_is_reallocated = false;
|
||||
char* old_base;
|
||||
unsigned int size() { return _count; }
|
||||
|
||||
// manage data memory allocation (add as much as memory it is needed)
|
||||
if (((_current - _base) + size) > _total_size)
|
||||
{
|
||||
// calc nb of needed pages
|
||||
unsigned long page_number = 1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK;
|
||||
_total_size += page_number * ALLOC_STACK_CHUNK;
|
||||
// stack access (stack_level=0=first out)
|
||||
object* get_obj(unsigned int stack_level) {
|
||||
return seq_obj(_count - stack_level - 1);
|
||||
}
|
||||
|
||||
old_base = _base;
|
||||
_base = (char*)realloc(_base, _total_size);
|
||||
object* operator[](unsigned int stack_level) {
|
||||
return seq_obj(_count - stack_level - 1);
|
||||
}
|
||||
|
||||
_current = _base + (_current - old_base);
|
||||
data_is_reallocated = true;
|
||||
}
|
||||
object* back() {
|
||||
object* obj = NULL;
|
||||
if (_count > 0) obj = _base_pointer[_count - 1];
|
||||
return obj;
|
||||
}
|
||||
|
||||
// manage pointers memory allocation (add one page if needed)
|
||||
if ((_count + 1) > _total_count_pointer)
|
||||
{
|
||||
_base_pointer = (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK);
|
||||
_total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object));
|
||||
}
|
||||
unsigned int get_len(unsigned int index) {
|
||||
return seq_len(_count - index - 1);
|
||||
}
|
||||
|
||||
// recalc object pointers in case of base reallocation
|
||||
if (data_is_reallocated)
|
||||
{
|
||||
for(int i = 0; i < _count; i++)
|
||||
{
|
||||
_base_pointer[i] = (object*)(_base + ((char*)_base_pointer[i] - old_base));
|
||||
if (_base_pointer[i]->_type == cmd_number)
|
||||
((number*)_base_pointer[i])->move();
|
||||
else if (_base_pointer[i]->_type == cmd_complex)
|
||||
((complex*)_base_pointer[i])->move();
|
||||
}
|
||||
}
|
||||
cmd_type_t get_type(unsigned int index) {
|
||||
return seq_type(_count - index - 1);
|
||||
}
|
||||
|
||||
// manage stack itself
|
||||
_base_pointer[_count++] = (object*)_current;
|
||||
allocated = (object*)_current;
|
||||
_current += size;
|
||||
// sequential access (index is counted from front)
|
||||
object* seq_obj(unsigned int index) {
|
||||
object* obj = NULL;
|
||||
if (index < _count) obj = _base_pointer[index];
|
||||
return obj;
|
||||
}
|
||||
|
||||
// init object
|
||||
allocated->_type = type;
|
||||
allocated->_size = size;
|
||||
if (type == cmd_number)
|
||||
((number*)allocated)->init();
|
||||
else if (type == cmd_complex)
|
||||
((complex*)allocated)->init();
|
||||
unsigned int seq_len(unsigned int index) {
|
||||
unsigned int len = 0;
|
||||
if (index < _count) len = _base_pointer[index]->_size;
|
||||
return len;
|
||||
}
|
||||
|
||||
return allocated;
|
||||
}
|
||||
cmd_type_t seq_type(unsigned int index) {
|
||||
cmd_type_t type = cmd_undef;
|
||||
if (index < _count) type = _base_pointer[index]->_type;
|
||||
return type;
|
||||
}
|
||||
|
||||
object* pop_back(int pop_count = 1)
|
||||
{
|
||||
object* back = NULL;
|
||||
private:
|
||||
char* _base;
|
||||
char* _current;
|
||||
object** _base_pointer;
|
||||
|
||||
// pop several entries, return the last
|
||||
while (pop_count-- > 0)
|
||||
{
|
||||
if (_count > 0)
|
||||
{
|
||||
_current = (char*)_base_pointer[--_count];
|
||||
back = (object*)_current;
|
||||
}
|
||||
}
|
||||
|
||||
return back;
|
||||
}
|
||||
|
||||
unsigned int size()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
// stack access (stack_level=0=first out)
|
||||
object* get_obj(unsigned int stack_level)
|
||||
{
|
||||
return seq_obj(_count - stack_level - 1);
|
||||
}
|
||||
|
||||
object* operator[](unsigned int stack_level)
|
||||
{
|
||||
return seq_obj(_count - stack_level - 1);
|
||||
}
|
||||
|
||||
object* back()
|
||||
{
|
||||
object* obj = NULL;
|
||||
if (_count>0)
|
||||
obj = _base_pointer[_count - 1];
|
||||
return obj;
|
||||
}
|
||||
|
||||
unsigned int get_len(unsigned int index)
|
||||
{
|
||||
return seq_len(_count - index - 1);
|
||||
}
|
||||
|
||||
cmd_type_t get_type(unsigned int index)
|
||||
{
|
||||
return seq_type(_count - index - 1);
|
||||
}
|
||||
|
||||
// sequential access (index is counted from front)
|
||||
object* seq_obj(unsigned int index)
|
||||
{
|
||||
object* obj = NULL;
|
||||
if (index<_count)
|
||||
obj = _base_pointer[index];
|
||||
return obj;
|
||||
}
|
||||
|
||||
unsigned int seq_len(unsigned int index)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
if (index<_count)
|
||||
len = _base_pointer[index]->_size;
|
||||
return len;
|
||||
}
|
||||
|
||||
cmd_type_t seq_type(unsigned int index)
|
||||
{
|
||||
cmd_type_t type = cmd_undef;
|
||||
if (index<_count)
|
||||
type = _base_pointer[index]->_type;
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
char* _base;
|
||||
char* _current;
|
||||
object** _base_pointer;
|
||||
|
||||
unsigned int _count;//stack count
|
||||
unsigned int _total_count_pointer;//total number of possible pointers
|
||||
unsigned int _total_size;//total allocated data size in bytes
|
||||
unsigned int _count; // stack count
|
||||
unsigned int _total_count_pointer; // total number of possible pointers
|
||||
unsigned int _total_size; // total allocated data size in bytes
|
||||
};
|
||||
|
||||
//
|
||||
class heap : public stack
|
||||
{
|
||||
public:
|
||||
heap() { }
|
||||
virtual ~heap() { }
|
||||
class heap : public stack {
|
||||
public:
|
||||
heap() {}
|
||||
virtual ~heap() {}
|
||||
|
||||
object* add(const string name, object* obj, unsigned int size)
|
||||
{
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
object* local = NULL;
|
||||
object* add(const string name, object* obj, unsigned int size) {
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
object* local = NULL;
|
||||
|
||||
// variable does not exist in heap or already exists but its size is too short -> allocate
|
||||
if (i!=_map.end())
|
||||
local = seq_obj(i->second);
|
||||
// variable does not exist in heap or already exists but its size is too
|
||||
// short -> allocate
|
||||
if (i != _map.end()) local = seq_obj(i->second);
|
||||
|
||||
if (local==NULL || (local!=NULL && size>local->_size))
|
||||
{
|
||||
copy_and_push_back(obj, *this, size);
|
||||
_map[name] = ((stack*)this)->size()-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// variable already exists in heap but previous was larger -> don't reallocate
|
||||
// copy a whole stack entry and push it back to another stack
|
||||
memcpy(local, obj, size);
|
||||
if (local->_type == cmd_number)
|
||||
((number*)local)->move();
|
||||
else if (local->_type == cmd_complex)
|
||||
((complex*)local)->move();
|
||||
}
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
bool get(const string name, object*& obj, unsigned int& size)
|
||||
{
|
||||
bool ret = false;
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
|
||||
if (i!=_map.end())
|
||||
{
|
||||
obj = seq_obj(i->second);
|
||||
size = obj->_size;
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
if (local == NULL || (local != NULL && size > local->_size)) {
|
||||
copy_and_push_back(obj, *this, size);
|
||||
_map[name] = ((stack*)this)->size() - 1;
|
||||
} else {
|
||||
// variable already exists in heap but previous was larger -> don't
|
||||
// reallocate copy a whole stack entry and push it back to another stack
|
||||
memcpy(local, obj, size);
|
||||
if (local->_type == cmd_number)
|
||||
((number*)local)->move();
|
||||
else if (local->_type == cmd_complex)
|
||||
((complex*)local)->move();
|
||||
}
|
||||
|
||||
bool replace_value(const string name, object* obj, unsigned int size)
|
||||
{
|
||||
bool ret=false;
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
return local;
|
||||
}
|
||||
|
||||
if (i!=_map.end())
|
||||
{
|
||||
object* obj_dst = seq_obj(i->second);
|
||||
if (size<=obj_dst->_size)
|
||||
{
|
||||
(void)memcpy(obj_dst, obj, size);
|
||||
if (obj_dst->_type == cmd_number)
|
||||
((number*)obj_dst)->move();
|
||||
else if (obj_dst->_type == cmd_complex)
|
||||
((complex*)obj_dst)->move();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
bool get(const string name, object*& obj, unsigned int& size) {
|
||||
bool ret = false;
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
|
||||
if (i != _map.end()) {
|
||||
obj = seq_obj(i->second);
|
||||
size = obj->_size;
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool exist(const string name)
|
||||
{
|
||||
return (_map.find(name) != _map.end());
|
||||
bool replace_value(const string name, object* obj, unsigned int size) {
|
||||
bool ret = false;
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
|
||||
if (i != _map.end()) {
|
||||
object* obj_dst = seq_obj(i->second);
|
||||
if (size <= obj_dst->_size) {
|
||||
(void)memcpy(obj_dst, obj, size);
|
||||
if (obj_dst->_type == cmd_number)
|
||||
((number*)obj_dst)->move();
|
||||
else if (obj_dst->_type == cmd_complex)
|
||||
((complex*)obj_dst)->move();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool get_by_index(int num, string& name, object*& obj, unsigned int& size)
|
||||
{
|
||||
if (num>=0 && num<(int)_map.size())
|
||||
{
|
||||
object* local;
|
||||
map<string, unsigned int>::iterator i= _map.begin();
|
||||
bool exist(const string name) { return (_map.find(name) != _map.end()); }
|
||||
|
||||
for(int j = 0; j < num; j++)
|
||||
i++;
|
||||
bool get_by_index(int num, string& name, object*& obj, unsigned int& size) {
|
||||
if (num >= 0 && num < (int)_map.size()) {
|
||||
object* local;
|
||||
map<string, unsigned int>::iterator i = _map.begin();
|
||||
|
||||
local = (object*)seq_obj(i->second);
|
||||
name = i->first;
|
||||
obj = local;
|
||||
size = local->_size;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
for (int j = 0; j < num; j++) i++;
|
||||
|
||||
local = (object*)seq_obj(i->second);
|
||||
name = i->first;
|
||||
obj = local;
|
||||
size = local->_size;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool erase(const string& name) {
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
bool ret = false;
|
||||
|
||||
if (i != _map.end()) {
|
||||
// remove variable from map
|
||||
_map.erase(i->first);
|
||||
ret = true;
|
||||
|
||||
// TODO: remove unused stack entries
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool erase(const string& name)
|
||||
{
|
||||
map<string, unsigned int>::iterator i = _map.find(name);
|
||||
bool ret = false;
|
||||
|
||||
if (i != _map.end())
|
||||
{
|
||||
// remove variable from map
|
||||
_map.erase(i->first);
|
||||
ret = true;
|
||||
|
||||
// TODO: remove unused stack entries
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void erase_all(void)
|
||||
{
|
||||
// map
|
||||
_map.erase(_map.begin(), _map.end());
|
||||
void erase_all(void) {
|
||||
// map
|
||||
_map.erase(_map.begin(), _map.end());
|
||||
|
||||
// and stack
|
||||
((stack*)this)->erase();
|
||||
}
|
||||
// and stack
|
||||
((stack*)this)->erase();
|
||||
}
|
||||
|
||||
unsigned int count_vars() { return _map.size(); }
|
||||
unsigned int count_vars() { return _map.size(); }
|
||||
|
||||
private:
|
||||
map<string, unsigned int> _map;
|
||||
private:
|
||||
map<string, unsigned int> _map;
|
||||
};
|
||||
|
||||
#endif // __stack_h__
|
||||
#endif // __stack_h__
|
||||
|
|
|
@ -15,8 +15,9 @@ static const char description[] =
|
|||
"using " ATTR_BOLD "GMP" ATTR_OFF " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n"
|
||||
ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING " under GNU LGPL\n"
|
||||
"and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n";
|
||||
|
||||
|
||||
// syntax
|
||||
static const char syntax[] =
|
||||
ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\n"
|
||||
"with optional command = list of commands";
|
||||
ATTR_BOLD "Syntax" ATTR_OFF
|
||||
": rpn [command]\n"
|
||||
"with optional command = list of commands";
|
||||
|
|
Loading…
Reference in a new issue