mirror of
https://github.com/louisrubet/rpn
synced 2025-02-11 20:48:30 +01:00
First step: lexer, entries and number outputs with new libbf decimal
This commit is contained in:
parent
0c8bc70ab9
commit
2ff0a3db88
17 changed files with 122 additions and 115 deletions
9
.gitmodules
vendored
9
.gitmodules
vendored
|
@ -1,9 +1,6 @@
|
||||||
[submodule "linenoise-ng"]
|
[submodule "linenoise-ng"]
|
||||||
path = linenoise-ng
|
path = linenoise-ng
|
||||||
url = https://github.com/louisrubet/linenoise-ng.git
|
url = https://github.com/louisrubet/linenoise-ng.git
|
||||||
[submodule "mpreal"]
|
[submodule "libbfdec-cpp"]
|
||||||
path = mpreal
|
path = libbfdec-cpp
|
||||||
url = https://github.com/advanpix/mpreal
|
url = git@github.com:louisrubet/libbfdec-cpp.git
|
||||||
[submodule "libbf"]
|
|
||||||
path = libbf
|
|
||||||
url = https://github.com/louisrubet/libbf
|
|
||||||
|
|
|
@ -31,22 +31,14 @@ set(RPN_LICENSE "LGPLv3")
|
||||||
set(RPN_LICENSE_FILE "${PROJECT_SOURCE_DIR}/LICENSE")
|
set(RPN_LICENSE_FILE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||||
set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
|
|
||||||
# custom linenoise-ng
|
add_subdirectory(libbfdec-cpp)
|
||||||
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/linenoise-ng/.git")
|
|
||||||
execute_process(COMMAND git submodule init ${PROJECT_SOURCE_DIR}/linenoise-ng)
|
|
||||||
execute_process(COMMAND git submodule update ${PROJECT_SOURCE_DIR}/linenoise-ng)
|
|
||||||
execute_process(COMMAND git checkout v1.1.4-rpn WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/linenoise-ng)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# custom mpreal
|
|
||||||
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/mpreal/.git")
|
|
||||||
execute_process(COMMAND git submodule init ${PROJECT_SOURCE_DIR}/mpreal)
|
|
||||||
execute_process(COMMAND git submodule update ${PROJECT_SOURCE_DIR}/mpreal)
|
|
||||||
execute_process(COMMAND git checkout mpfrc++-3.6.9 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/mpreal)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# includes
|
# includes
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng/include ${PROJECT_SOURCE_DIR}/mpreal)
|
include_directories(${PROJECT_SOURCE_DIR}/src
|
||||||
|
${PROJECT_SOURCE_DIR}/linenoise-ng/include
|
||||||
|
${PROJECT_SOURCE_DIR}/libbfdec-cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/libbfdec-cpp/libbf
|
||||||
|
${PROJECT_SOURCE_DIR}/libbfdec-cpp/quickjs-fake)
|
||||||
|
|
||||||
# src
|
# src
|
||||||
set(RPN_SRC_FILES
|
set(RPN_SRC_FILES
|
||||||
|
@ -54,13 +46,13 @@ set(RPN_SRC_FILES
|
||||||
${PROJECT_SOURCE_DIR}/src/program.cc
|
${PROJECT_SOURCE_DIR}/src/program.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/main.cc
|
${PROJECT_SOURCE_DIR}/src/main.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/object.cc
|
${PROJECT_SOURCE_DIR}/src/object.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/mpreal-out.cc
|
# ${PROJECT_SOURCE_DIR}/src/mpreal-out.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/lexer.cc
|
${PROJECT_SOURCE_DIR}/src/lexer.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/input.cc
|
${PROJECT_SOURCE_DIR}/src/input.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-branch.cc
|
# ${PROJECT_SOURCE_DIR}/src/rpn-branch.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
|
# ${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
|
# ${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
|
||||||
|
@ -69,7 +61,11 @@ set(RPN_SRC_FILES
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
|
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-trig.cc)
|
# ${PROJECT_SOURCE_DIR}/src/rpn-trig.cc
|
||||||
|
# ${PROJECT_SOURCE_DIR}/libbfdec-cpp/libbf/libbf.c
|
||||||
|
# ${PROJECT_SOURCE_DIR}/libbfdec-cpp/libbf/cutils.c
|
||||||
|
# ${PROJECT_SOURCE_DIR}/libbfdec-cpp/libbfdec++.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(LINENOISE_NG_SRC_FILES
|
set(LINENOISE_NG_SRC_FILES
|
||||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
||||||
|
@ -77,16 +73,14 @@ set(LINENOISE_NG_SRC_FILES
|
||||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp)
|
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp)
|
||||||
|
|
||||||
# compiler options
|
# compiler options
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set_source_files_properties(${RPN_SRC_FILES} COMPILE_FLAGS "-Wall -Wextra -pedantic -Wno-missing-field-initializers")
|
set_source_files_properties(${RPN_SRC_FILES} COMPILE_FLAGS "-Wall -Wextra -pedantic -Wno-missing-field-initializers")
|
||||||
|
add_compile_options("$<$<CONFIG:DEBUG>:-O0;-g3;-ggdb>" "$<$<CONFIG:RELEASE>:-O3>")
|
||||||
|
|
||||||
add_compile_options("-std=c++20"
|
# executable
|
||||||
"$<$<CONFIG:DEBUG>:-O0;-g3;-ggdb>"
|
add_executable(rpn ${RPN_SRC_FILES} ${LINENOISE_NG_SRC_FILES} ${LIBBF_SRC_FILES})
|
||||||
"$<$<CONFIG:RELEASE>:-O3>")
|
target_link_libraries(rpn libbf)
|
||||||
|
|
||||||
add_executable(rpn ${RPN_SRC_FILES} ${LINENOISE_NG_SRC_FILES})
|
|
||||||
|
|
||||||
target_link_libraries(rpn mpfr)
|
|
||||||
target_link_libraries(rpn gmp)
|
|
||||||
|
|
||||||
# install
|
# install
|
||||||
install(TARGETS rpn DESTINATION bin)
|
install(TARGETS rpn DESTINATION bin)
|
||||||
|
|
1
libbf
1
libbf
|
@ -1 +0,0 @@
|
||||||
Subproject commit 19bd01375827e13bd7ded3c82b9a5f50cc3bf2f4
|
|
1
libbfdec-cpp
Submodule
1
libbfdec-cpp
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1a1ce5a93ca57abb548066f67581e9137549aeb1
|
1
mpreal
1
mpreal
|
@ -1 +0,0 @@
|
||||||
Subproject commit 269a03782fa0b87c20470976b88677266c5423ad
|
|
|
@ -45,8 +45,8 @@ bool Lexer::Analyse(const string& entry, map<string, ReservedWord>& keywords, ve
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lexer::Trim(string& s) {
|
void Lexer::Trim(string& s) {
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
s.erase(s.begin(), std::ranges::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
s.erase(std::ranges::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lexer::ParseString(const string& entry, size_t idx, size_t& next_idx,
|
bool Lexer::ParseString(const string& entry, size_t idx, size_t& next_idx,
|
||||||
|
@ -167,7 +167,7 @@ bool Lexer::GetNumberAt(const string& entry, size_t idx, size_t& next_idx, int&
|
||||||
if (base < 2 || base > 62) return false;
|
if (base < 2 || base > 62) return false;
|
||||||
if (numberIdx != 0) token = token.substr(numberIdx);
|
if (numberIdx != 0) token = token.substr(numberIdx);
|
||||||
*r = new mpreal;
|
*r = new mpreal;
|
||||||
if (mpfr_set_str((*r)->mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) {
|
if (bfdec_atof(&(*r)->toBfdec(), token.c_str(), nullptr, (limb_t)Bfdec::get_default_prec(), (bf_flags_t)Bfdec::get_default_rnd()) == 0) {
|
||||||
if (!positive) *(*r) = -*(*r);
|
if (!positive) *(*r) = -*(*r);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
#ifndef SRC_LEXER_H_
|
#ifndef SRC_LEXER_H_
|
||||||
#define SRC_LEXER_H_
|
#define SRC_LEXER_H_
|
||||||
|
|
||||||
#include <mpreal.h>
|
#include <libbfdec++.h>
|
||||||
using mpfr::mpreal;
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
using std::cerr;
|
using std::cerr;
|
||||||
|
|
||||||
// internal includes
|
// internal includes
|
||||||
|
@ -119,7 +120,7 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mpfr_free_cache();
|
Bfdec::clear_cache();
|
||||||
|
|
||||||
if (ret != kOk) return EXIT_FAILURE;
|
if (ret != kOk) return EXIT_FAILURE;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
@ -2,11 +2,15 @@
|
||||||
|
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// number statics
|
// number statics
|
||||||
Number::mode_enum Number::mode = Number::kDefaultMode;
|
Number::mode_enum Number::mode = Number::kDefaultMode;
|
||||||
int Number::digits = kDefaultDecimalDigits;
|
limb_t Number::digits = kDefaultDecimalDigits;
|
||||||
|
|
||||||
ostream& Number::ShowValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base) {
|
ostream& Number::ShowValue(ostream& out, const Bfdec& value, mode_enum mode, int digits, int base) {
|
||||||
|
return out << bfdec_ftoa(NULL, &value.toBfdec(), (limb_t)BF_PREC_INF, (bf_flags_t)(BF_RNDZ | BF_FTOA_FORMAT_FREE));
|
||||||
|
#if 0
|
||||||
stringstream format;
|
stringstream format;
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case 10:
|
case 10:
|
||||||
|
@ -40,4 +44,5 @@ ostream& Number::ShowValue(ostream& out, const mpreal& value, mode_enum mode, in
|
||||||
// base other than 2, 10, 16
|
// base other than 2, 10, 16
|
||||||
return MprealOutputNBase(out, base, value);
|
return MprealOutputNBase(out, base, value);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
33
src/object.h
33
src/object.h
|
@ -3,8 +3,7 @@
|
||||||
#ifndef SRC_OBJECT_H_
|
#ifndef SRC_OBJECT_H_
|
||||||
#define SRC_OBJECT_H_
|
#define SRC_OBJECT_H_
|
||||||
|
|
||||||
#include <mpreal.h>
|
#include <libbfdec++.h>
|
||||||
using mpfr::mpreal;
|
|
||||||
|
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
@ -12,8 +11,6 @@ using mpfr::mpreal;
|
||||||
#include <string>
|
#include <string>
|
||||||
using std::complex, std::ostream, std::string, std::stringstream;
|
using std::complex, std::ostream, std::string, std::stringstream;
|
||||||
|
|
||||||
#include "mpreal-out.h"
|
|
||||||
|
|
||||||
// definitions for objects
|
// definitions for objects
|
||||||
///
|
///
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -81,12 +78,14 @@ union object_cb_t {
|
||||||
///
|
///
|
||||||
struct Number : Object {
|
struct Number : Object {
|
||||||
Number() : Object(kNumber), base(10) {}
|
Number() : Object(kNumber), base(10) {}
|
||||||
explicit Number(const mpreal& value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
explicit Number(const Bfdec& value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
explicit Number(int value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
explicit Number(int64_t value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
explicit Number(uint64_t value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
explicit Number(uint64_t value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
|
explicit Number(bool value__, int base__ = 10) : Object(kNumber), base(base__), value(value__ ? 1 : 0) {}
|
||||||
|
explicit Number(int value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
|
|
||||||
int base;
|
int base;
|
||||||
mpreal value;
|
Bfdec value;
|
||||||
|
|
||||||
virtual Object* Clone() { return new Number(value, base); }
|
virtual Object* Clone() { return new Number(value, base); }
|
||||||
virtual string Name() { return string("number"); }
|
virtual string Name() { return string("number"); }
|
||||||
|
@ -98,30 +97,30 @@ struct Number : Object {
|
||||||
static constexpr mode_enum kDefaultMode = Number::kStd;
|
static constexpr mode_enum kDefaultMode = Number::kStd;
|
||||||
|
|
||||||
// precision
|
// precision
|
||||||
static constexpr mpfr_prec_t kMpfrDefaultPrecBits = 128;
|
static constexpr mp_prec_t kMpfrDefaultPrecBits = 128;
|
||||||
static constexpr int kDefaultDecimalDigits = 38;
|
static constexpr int kDefaultDecimalDigits = 38;
|
||||||
static int digits;
|
static limb_t digits;
|
||||||
|
|
||||||
// clang-format on
|
static ostream& ShowValue(ostream& out, const Bfdec& value, mode_enum mode, int digits, int base);
|
||||||
static ostream& ShowValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base);
|
|
||||||
|
static void* rpn_bf_realloc(void*, void* ptr, size_t size);
|
||||||
|
static bf_context_t rpn_bf_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief stack objects inheriting Object
|
/// @brief stack objects inheriting Object
|
||||||
///
|
///
|
||||||
struct Complex : Object {
|
struct Complex : Object {
|
||||||
Complex() : Object(kComplex), re_base(10), im_base(10) {}
|
Complex() : Object(kComplex), re_base(10), im_base(10) {}
|
||||||
explicit Complex(complex<mpreal>& value__, int re_base__ = 10, int im_base__ = 10)
|
explicit Complex(complex<Bfdec>& value__, int re_base__ = 10, int im_base__ = 10)
|
||||||
: Object(kComplex), re_base(re_base__), im_base(im_base__) {
|
: Object(kComplex), re_base(re_base__), im_base(im_base__), value(value__) {}
|
||||||
value = value__;
|
explicit Complex(Bfdec& re__, Bfdec& im__, int re_base__ = 10, int im_base__ = 10)
|
||||||
}
|
|
||||||
explicit Complex(mpreal& re__, mpreal& im__, int re_base__ = 10, int im_base__ = 10)
|
|
||||||
: Object(kComplex), re_base(re_base__), im_base(im_base__) {
|
: Object(kComplex), re_base(re_base__), im_base(im_base__) {
|
||||||
value.real(re__);
|
value.real(re__);
|
||||||
value.imag(im__);
|
value.imag(im__);
|
||||||
}
|
}
|
||||||
|
|
||||||
int re_base, im_base;
|
int re_base, im_base;
|
||||||
complex<mpreal> value;
|
complex<Bfdec> value;
|
||||||
|
|
||||||
virtual Object* Clone() { return new Complex(value, re_base, im_base); }
|
virtual Object* Clone() { return new Complex(value, re_base, im_base); }
|
||||||
virtual string Name() { return string("complex"); }
|
virtual string Name() { return string("complex"); }
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// Copyright (c) 2014-2022 Louis Rubet
|
// Copyright (c) 2014-2022 Louis Rubet
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
|
|
||||||
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
|
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
|
||||||
|
@ -24,6 +27,7 @@ vector<Program::keyword_t> Program::keywords_ = {
|
||||||
{kKeyword, "-", {.prog = &Program::RpnMinus}, "substraction"},
|
{kKeyword, "-", {.prog = &Program::RpnMinus}, "substraction"},
|
||||||
{kKeyword, "*", {.prog = &Program::RpnMul}, "multiplication"},
|
{kKeyword, "*", {.prog = &Program::RpnMul}, "multiplication"},
|
||||||
{kKeyword, "/", {.prog = &Program::RpnDiv}, "division"},
|
{kKeyword, "/", {.prog = &Program::RpnDiv}, "division"},
|
||||||
|
#if 0
|
||||||
{kKeyword, "inv", {.prog = &Program::RpnInv}, "inverse"},
|
{kKeyword, "inv", {.prog = &Program::RpnInv}, "inverse"},
|
||||||
{kKeyword, "chs", {.prog = &Program::RpnNeg}, "negation"},
|
{kKeyword, "chs", {.prog = &Program::RpnNeg}, "negation"},
|
||||||
{kKeyword, "neg", {.prog = &Program::RpnNeg}, ""},
|
{kKeyword, "neg", {.prog = &Program::RpnNeg}, ""},
|
||||||
|
@ -136,7 +140,7 @@ vector<Program::keyword_t> Program::keywords_ = {
|
||||||
{kBranch, "until", {.branch = &Program::RpnUntil}, "used with do"},
|
{kBranch, "until", {.branch = &Program::RpnUntil}, "used with do"},
|
||||||
{kBranch, "while", {.branch = &Program::RpnWhile}, "while <test-instruction> repeat <loop-instructions> end"},
|
{kBranch, "while", {.branch = &Program::RpnWhile}, "while <test-instruction> repeat <loop-instructions> end"},
|
||||||
{kBranch, "repeat", {.branch = &Program::RpnRepeat}, "used with while"},
|
{kBranch, "repeat", {.branch = &Program::RpnRepeat}, "used with while"},
|
||||||
|
#endif
|
||||||
// STORE
|
// STORE
|
||||||
{kUndef, "", {.prog = nullptr}, "\nSTORE"},
|
{kUndef, "", {.prog = nullptr}, "\nSTORE"},
|
||||||
{kKeyword, "sto", {.prog = &Program::RpnSto}, "store a variable. ex: 1 'name' sto"},
|
{kKeyword, "sto", {.prog = &Program::RpnSto}, "store a variable. ex: 1 'name' sto"},
|
||||||
|
@ -149,6 +153,7 @@ vector<Program::keyword_t> Program::keywords_ = {
|
||||||
{kKeyword, "sto-", {.prog = &Program::RpnStosub}, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
{kKeyword, "sto-", {.prog = &Program::RpnStosub}, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||||
{kKeyword, "sto*", {.prog = &Program::RpnStomul}, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
{kKeyword, "sto*", {.prog = &Program::RpnStomul}, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||||
{kKeyword, "sto/", {.prog = &Program::RpnStodiv}, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
{kKeyword, "sto/", {.prog = &Program::RpnStodiv}, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||||
|
#if 0
|
||||||
{kKeyword, "sneg", {.prog = &Program::RpnStoneg}, "negate a variable. ex: 'name' sneg"},
|
{kKeyword, "sneg", {.prog = &Program::RpnStoneg}, "negate a variable. ex: 'name' sneg"},
|
||||||
{kKeyword, "sinv", {.prog = &Program::RpnStoinv}, "inverse a variable. ex: 1 'name' sinv"},
|
{kKeyword, "sinv", {.prog = &Program::RpnStoinv}, "inverse a variable. ex: 1 'name' sinv"},
|
||||||
|
|
||||||
|
@ -195,6 +200,7 @@ vector<Program::keyword_t> Program::keywords_ = {
|
||||||
{kKeyword, "time", {.prog = &Program::RpnTime}, "local time in ISO 8601 format"},
|
{kKeyword, "time", {.prog = &Program::RpnTime}, "local time in ISO 8601 format"},
|
||||||
{kKeyword, "date", {.prog = &Program::RpnDate}, "local date in ISO 8601 format"},
|
{kKeyword, "date", {.prog = &Program::RpnDate}, "local date in ISO 8601 format"},
|
||||||
{kKeyword, "ticks", {.prog = &Program::RpnTicks}, "local date and time in µs"}
|
{kKeyword, "ticks", {.prog = &Program::RpnTicks}, "local date and time in µs"}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <mpreal.h>
|
#include <libbfdec++.h>
|
||||||
using mpfr::mpreal;
|
|
||||||
|
|
||||||
// internal includes
|
// internal includes
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
|
|
@ -13,9 +13,9 @@ using std::cout, std::string, std::pair;
|
||||||
#define ATTR_OFF "\33[0m"
|
#define ATTR_OFF "\33[0m"
|
||||||
|
|
||||||
#define MPFR_ROUND \
|
#define MPFR_ROUND \
|
||||||
{"nearest (even)", MPFR_RNDN}, {"toward zero", MPFR_RNDZ}, {"toward +inf", MPFR_RNDU}, {"toward -inf", MPFR_RNDD}, \
|
{"nearest (even)", BF_RNDN}, {"toward zero", BF_RNDZ}, {"toward +inf", BF_RNDU}, {"toward -inf", BF_RNDD}, \
|
||||||
{"away from zero", MPFR_RNDA}, {"faithful rounding", MPFR_RNDF}, { \
|
{"away from zero", BF_RNDA}, {"faithful rounding", BF_RNDF}, { \
|
||||||
"nearest (away from zero)", MPFR_RNDNA \
|
"nearest (away from zero)", BF_RNDNA \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char _description[] =
|
static const char _description[] =
|
||||||
|
@ -75,7 +75,7 @@ void Program::RpnHelp() {
|
||||||
// bits precision, decimal digits and rounding mode
|
// bits precision, decimal digits and rounding mode
|
||||||
cout << " with " << Number::digits << " digits after the decimal point" << endl;
|
cout << " with " << Number::digits << " digits after the decimal point" << endl;
|
||||||
cout << "Current floating point precision is " << static_cast<int>(mpreal::get_default_prec()) << " bits" << endl;
|
cout << "Current floating point precision is " << static_cast<int>(mpreal::get_default_prec()) << " bits" << endl;
|
||||||
vector<pair<string, mpfr_rnd_t>> rnd{MPFR_ROUND};
|
vector<pair<string, mp_rnd_t>> rnd{MPFR_ROUND};
|
||||||
for (auto& rn : rnd)
|
for (auto& rn : rnd)
|
||||||
if (rn.second == mpreal::get_default_rnd()) {
|
if (rn.second == mpreal::get_default_rnd()) {
|
||||||
cout << "Current rounding mode is '" << rn.first << '\'' << endl;
|
cout << "Current rounding mode is '" << rn.first << '\'' << endl;
|
||||||
|
@ -190,14 +190,14 @@ void Program::RpnPrecision() {
|
||||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
|
|
||||||
// set precision
|
// set precision
|
||||||
mpfr_prec_t prec = static_cast<int>(stack_.value<Number>(0).toLong());
|
mp_prec_t prec = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||||
if (prec >= MPFR_PREC_MIN && prec <= MPFR_PREC_MAX) {
|
if (prec >= BF_PREC_MIN && prec <= BF_PREC_MAX) {
|
||||||
mpreal::set_default_prec(prec);
|
mpreal::set_default_prec(prec);
|
||||||
|
|
||||||
// modify digits seen by user if std mode
|
// modify digits seen by user if std mode
|
||||||
if (Number::mode == Number::kStd) {
|
if (Number::mode == Number::kStd) {
|
||||||
// calc max nb of digits user can see with the current bit precision
|
// calc max nb of digits user can see with the current bit precision
|
||||||
Number::digits = mpfr::bits2digits(mpreal::get_default_prec());
|
Number::digits = Bfdec::bits2digits(mpreal::get_default_prec());
|
||||||
}
|
}
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
|
@ -211,7 +211,7 @@ void Program::RpnRound() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||||
|
|
||||||
map<string, mpfr_rnd_t> matchRound{MPFR_ROUND};
|
map<string, mp_rnd_t> matchRound{MPFR_ROUND};
|
||||||
|
|
||||||
auto found = matchRound.find(stack_.value<String>(0));
|
auto found = matchRound.find(stack_.value<String>(0));
|
||||||
if (found != matchRound.end())
|
if (found != matchRound.end())
|
||||||
|
|
|
@ -12,16 +12,16 @@ void Program::RpnPlus() {
|
||||||
} else if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
} else if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||||
stack_.value<Number>(1) += stack_.value<Number>(0);
|
stack_.value<Number>(1) += stack_.value<Number>(0);
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
// } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) += stack_.value<Complex>(0);
|
// stack_.value<Complex>(1) += stack_.value<Complex>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) += stack_.value<Number>(0);
|
// stack_.value<Complex>(1) += stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
||||||
RpnSwap();
|
// RpnSwap();
|
||||||
stack_.value<Complex>(1) += stack_.value<Number>(0);
|
// stack_.value<Complex>(1) += stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kBadOperandType);
|
ERROR_CONTEXT(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
@ -34,16 +34,16 @@ void Program::RpnMinus() {
|
||||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||||
stack_.value<Number>(1) -= stack_.value<Number>(0);
|
stack_.value<Number>(1) -= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) -= stack_.value<Complex>(0);
|
// stack_.value<Complex>(1) -= stack_.value<Complex>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) -= stack_.value<Number>(0);
|
// stack_.value<Complex>(1) -= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
||||||
RpnSwap();
|
// RpnSwap();
|
||||||
stack_.value<Complex>(1) = stack_.value<Number>(0) - stack_.value<Complex>(1);
|
// stack_.value<Complex>(1) = stack_.value<Number>(0) - stack_.value<Complex>(1);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kBadOperandType);
|
ERROR_CONTEXT(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
@ -56,16 +56,16 @@ void Program::RpnMul() {
|
||||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||||
stack_.value<Number>(1) *= stack_.value<Number>(0);
|
stack_.value<Number>(1) *= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) *= stack_.value<Complex>(0);
|
// stack_.value<Complex>(1) *= stack_.value<Complex>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) *= stack_.value<Number>(0);
|
// stack_.value<Complex>(1) *= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
||||||
RpnSwap();
|
// RpnSwap();
|
||||||
stack_.value<Complex>(1) *= stack_.value<Number>(0);
|
// stack_.value<Complex>(1) *= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kBadOperandType);
|
ERROR_CONTEXT(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
@ -78,21 +78,22 @@ void Program::RpnDiv() {
|
||||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||||
stack_.value<Number>(1) /= stack_.value<Number>(0);
|
stack_.value<Number>(1) /= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) /= stack_.value<Complex>(0);
|
// stack_.value<Complex>(1) /= stack_.value<Complex>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
//} else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) {
|
||||||
stack_.value<Complex>(1) /= stack_.value<Number>(0);
|
// stack_.value<Complex>(1) /= stack_.value<Number>(0);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
//} else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) {
|
||||||
RpnSwap();
|
// RpnSwap();
|
||||||
stack_.value<Complex>(1) = stack_.value<Number>(0) / stack_.value<Complex>(1);
|
// stack_.value<Complex>(1) = stack_.value<Number>(0) / stack_.value<Complex>(1);
|
||||||
stack_.pop();
|
// stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kBadOperandType);
|
ERROR_CONTEXT(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/// @brief neg keyword implementation
|
/// @brief neg keyword implementation
|
||||||
///
|
///
|
||||||
void Program::RpnNeg() {
|
void Program::RpnNeg() {
|
||||||
|
@ -122,7 +123,7 @@ void Program::RpnInv() {
|
||||||
void Program::RpnPower() {
|
void Program::RpnPower() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||||
if (stack_.value<Number>(1) >= 0) {
|
if (stack_.value<Number>(1).gt0()) {
|
||||||
stack_.value<Number>(1) = pow(stack_.value<Number>(1), stack_.value<Number>(0));
|
stack_.value<Number>(1) = pow(stack_.value<Number>(1), stack_.value<Number>(0));
|
||||||
stack_.pop();
|
stack_.pop();
|
||||||
} else {
|
} else {
|
||||||
|
@ -387,3 +388,4 @@ void Program::RpnMax() {
|
||||||
stack_.value<Number>(0) = max(stack_.value<Number>(0), stack_.value<Number>(1));
|
stack_.value<Number>(0) = max(stack_.value<Number>(0), stack_.value<Number>(1));
|
||||||
stack_.erase(1);
|
stack_.erase(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// Copyright (c) 2014-2022 Louis Rubet
|
// Copyright (c) 2014-2022 Louis Rubet
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
|
|
||||||
|
@ -87,6 +90,7 @@ void Program::RpnStodiv(void) {
|
||||||
RpnSto();
|
RpnSto();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/// @brief stosneg keyword implementation
|
/// @brief stosneg keyword implementation
|
||||||
///
|
///
|
||||||
void Program::RpnStoneg(void) {
|
void Program::RpnStoneg(void) {
|
||||||
|
@ -118,6 +122,7 @@ void Program::RpnStoinv(void) {
|
||||||
RpnSwap();
|
RpnSwap();
|
||||||
RpnSto();
|
RpnSto();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// @brief rcl keyword implementation
|
/// @brief rcl keyword implementation
|
||||||
///
|
///
|
||||||
|
|
|
@ -51,9 +51,9 @@ void Program::RpnNum() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||||
if (stack_.value<String>(0).size() > 0)
|
if (stack_.value<String>(0).size() > 0)
|
||||||
stack_.push_front(new Number(stack_.value<String>(0)[0]));
|
stack_.push_front(new Number((int64_t)stack_.value<String>(0)[0]));
|
||||||
else
|
else
|
||||||
stack_.push_front(new Number(0));
|
stack_.push_front(new Number((int64_t)0));
|
||||||
stack_.erase(1);
|
stack_.erase(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// Copyright (c) 2014-2022 Louis Rubet
|
// Copyright (c) 2014-2022 Louis Rubet
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
using std::string;
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
Loading…
Add table
Reference in a new issue