mirror of
https://github.com/louisrubet/rpn
synced 2024-12-26 09:58:55 +01:00
#8: added functions date, time, ticks
This commit is contained in:
parent
55da6d7bea
commit
ff541e49a0
9 changed files with 159 additions and 39 deletions
|
@ -56,8 +56,9 @@ add_executable(
|
|||
${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-store.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-string.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test-core.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test-core.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-time.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
|
||||
|
|
27
MANUAL.md
27
MANUAL.md
|
@ -128,8 +128,8 @@ rpn> 7b1252 dec
|
|||
|keyword|description|
|
||||
|-|-|
|
||||
|`nop` | no operation
|
||||
|`help\|h\|?` | this help message
|
||||
|`quit\|q\|exit` | quit software
|
||||
|`help` `h` `?` | this help message
|
||||
|`quit` `q` `exit` | quit software
|
||||
|`version` | show rpn version
|
||||
|`uname` | show rpn complete identification string
|
||||
|`history`| see commands history
|
||||
|
@ -140,13 +140,13 @@ rpn> 7b1252 dec
|
|||
|-|-|
|
||||
|`+`| addition
|
||||
|`-`| substraction
|
||||
|`neg\|chs`| negation
|
||||
|`neg` `chs`| negation
|
||||
|`*`| multiplication
|
||||
|`/`| division
|
||||
|`inv`| inverse
|
||||
|`^\|pow`| power
|
||||
|`^` `pow`| power
|
||||
|`sqrt`| square root
|
||||
|`sq\|sqr`| square
|
||||
|`sq` `sqr`| square
|
||||
|`abs`| absolute value for a number or `sqrt(re*re+im*im)` for a complex
|
||||
|`dec`| decimal representation
|
||||
|`hex`| hexadecimal representation
|
||||
|
@ -220,7 +220,7 @@ rpn> 7b1252 dec
|
|||
|`drop`| drop first stack entry
|
||||
|`drop2`| drop 2 first stack entries
|
||||
|`dropn`| drop n first stack entries
|
||||
|`del\|erase`| drop all stack entries
|
||||
|`del` `erase`| drop all stack entries
|
||||
|`rot`| rotate 3 first stack entries
|
||||
|`dup`| duplicate first stack entry
|
||||
|`dup2`| duplicate 2 first stack entries
|
||||
|
@ -258,9 +258,9 @@ rpn> 7b1252 dec
|
|||
|`next`| used with start and for
|
||||
|`step`| used with start and for
|
||||
|`do`| do (instructions) until (condition) end
|
||||
|`until\|unti` | used with do
|
||||
|`while\|whil`| while (test-instruction) repeat (loop-instructions) end
|
||||
|`repeat\|repea`| used with while
|
||||
|`until` `unti` | used with do
|
||||
|`while` `whil`| while (test-instruction) repeat (loop-instructions) end
|
||||
|`repeat` `repea`| used with while
|
||||
|
||||
### store
|
||||
|
||||
|
@ -305,20 +305,23 @@ rpn> 7b1252 dec
|
|||
|keyword|description|
|
||||
|-|-|
|
||||
|`e`| Euler constant
|
||||
|`ln\|log`| logarithm base e
|
||||
|`ln` `log`| logarithm base e
|
||||
|`lnp1`| ln(1+x) which is useful when x is close to 0
|
||||
|`exp`| exponential
|
||||
|`expm`| exp(x)-1 which is useful when x is close to 0
|
||||
|`log10`| logarithm base 10
|
||||
|`alog10\|exp10`| exponential base 10
|
||||
|`alog10` `exp10`| exponential base 10
|
||||
|`log2`| logarithm base 2
|
||||
|`alog2\|exp2`| exponential base 2
|
||||
|`alog2` `exp2`| exponential base 2
|
||||
|`sinh`| hyperbolic sine
|
||||
|`asinh`| inverse hyperbolic sine
|
||||
|`cosh`| hyperbolic cosine
|
||||
|`acosh`| inverse hyperbolic cosine
|
||||
|`tanh`| hyperbolic tangent
|
||||
|`atanh`| inverse hyperbolic tangent
|
||||
|`time`| time in format HH.MMSSssssss
|
||||
|`date`| date in format (M)M.DDYYYY
|
||||
|`ticks`| system tick in µs
|
||||
|
||||
### default
|
||||
|
||||
|
|
36
README.md
36
README.md
|
@ -25,25 +25,31 @@ rpn> << -> x y << x y + ln >> >> 'P' sto
|
|||
### and a bunch of functions
|
||||
```
|
||||
rpn>
|
||||
Display all 147 possibilities? (y or n)
|
||||
nop chs bin min prec not depth else repeat sinv ln cosh
|
||||
help neg base max round same roll end repea eval log acosh
|
||||
h * sign re default swap rolld start sto -> lnp1 tanh
|
||||
? / % im type drop over for rcl pi exp atanh
|
||||
quit inv %CH conj > drop2 ->str next purge sin expm
|
||||
q ^ mod arg >= dropn str-> step vars asin log10
|
||||
exit pow fact c->r < del chr ift clusr cos alog10
|
||||
test sqrt mant r->c <= erase num ifte edit acos exp10
|
||||
version sq xpon p->r != rot size do sto+ tan log2
|
||||
uname sqr floor r->p == dup pos until sto- atan alog2
|
||||
history abs ceil std and dup2 sub unti sto* d->r exp2
|
||||
+ dec ip fix or dupn if while sto/ r->d sinh
|
||||
- hex fp sci xor pick then whil sneg e asinh
|
||||
Display all 150 possibilities? (y or n)
|
||||
nop pow fp >= dupn next sto* exp
|
||||
help sqrt min < pick step sto/ expm
|
||||
h sq max <= depth ift sneg log10
|
||||
? sqr re != roll ifte sinv alog10
|
||||
quit abs im == rolld do eval exp10
|
||||
q dec conj and over until -> log2
|
||||
exit hex arg or ->str unti pi alog2
|
||||
test bin c->r xor str-> while sin exp2
|
||||
version base r->c not chr whil asin sinh
|
||||
uname sign p->r same num repeat cos asinh
|
||||
history % r->p swap size repea acos cosh
|
||||
+ %CH std drop pos sto tan acosh
|
||||
- mod fix drop2 sub rcl atan tanh
|
||||
chs fact sci dropn if purge d->r atanh
|
||||
neg mant prec del then vars r->d time
|
||||
* xpon round erase else clusr e date
|
||||
/ floor default rot end edit ln ticks
|
||||
inv ceil type dup start sto+ log
|
||||
^ ip > dup2 for sto- lnp1
|
||||
```
|
||||
|
||||
## Download
|
||||
|
||||
deb, rpm and tgz files can be found [there](http://nvie.com/img/git-model@2x.png)
|
||||
deb, rpm and tgz files can be found [there](liv/)
|
||||
|
||||
## Manual
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ void program::entry_completion_generator(const char* text, linenoiseCompletions*
|
|||
int text_len = strnlen(text, 6);
|
||||
|
||||
// propose all keywords
|
||||
if (text_len == 0) {
|
||||
if (text_len == 0) {
|
||||
while (program::s_keywords[i].type != cmd_max) {
|
||||
if (program::s_keywords[i].fn != NULL)
|
||||
// add all keywords
|
||||
|
|
|
@ -202,12 +202,18 @@ program::keyword_t program::s_keywords[] = {
|
|||
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
||||
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
|
||||
|
||||
// TIME AND DATE
|
||||
{cmd_undef, "", NULL, "\nTIME AND DATE"},
|
||||
{cmd_keyword, "time", &program::rpn_time, "time in local format"},
|
||||
{cmd_keyword, "date", &program::rpn_date, "date in local format"},
|
||||
{cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"},
|
||||
|
||||
// end
|
||||
{cmd_max, "", NULL, ""},
|
||||
};
|
||||
|
||||
/// @brief run a program on a stack and a heap
|
||||
///
|
||||
///
|
||||
/// @param stk the stack, storing prog result
|
||||
/// @param hp the heap, storing variables
|
||||
/// @return ret_value see this type
|
||||
|
@ -305,12 +311,12 @@ ret_value program::run(stack& stk, heap& hp) {
|
|||
}
|
||||
|
||||
/// @brief stop a program
|
||||
///
|
||||
///
|
||||
///
|
||||
void program::stop() { interrupt_now = true; }
|
||||
|
||||
/// @brief return whether a branch object has a given name
|
||||
///
|
||||
///
|
||||
/// @param b the branch object
|
||||
/// @param str_to_compare the name
|
||||
/// @param len the name length
|
||||
|
@ -328,7 +334,7 @@ bool program::compare_branch(branch* b, const char* str_to_compare, int len) {
|
|||
/// this is needed before a program can be run
|
||||
/// inner members of branch or keyword objects are filled by this function
|
||||
/// these inner members store for example the index of the next keyword to execute etc.
|
||||
///
|
||||
///
|
||||
/// @return ret_value see this type
|
||||
///
|
||||
ret_value program::preprocess(void) {
|
||||
|
@ -558,7 +564,7 @@ ret_value program::preprocess(void) {
|
|||
}
|
||||
|
||||
/// @brief show the last error set
|
||||
///
|
||||
///
|
||||
/// @return ret_value see this type
|
||||
///
|
||||
ret_value program::show_error() {
|
||||
|
@ -578,7 +584,7 @@ ret_value program::show_error() {
|
|||
}
|
||||
|
||||
/// @brief record an error as the last error set and show it
|
||||
///
|
||||
///
|
||||
/// @param err the error to record
|
||||
/// @param context a context string
|
||||
/// @return ret_value see this type
|
||||
|
@ -591,7 +597,7 @@ ret_value program::show_error(ret_value err, string& context) {
|
|||
}
|
||||
|
||||
/// @brief record an error as the last error set and show it
|
||||
///
|
||||
///
|
||||
/// @param err the error to record
|
||||
/// @param context a context string
|
||||
/// @return ret_value see this type
|
||||
|
@ -604,7 +610,7 @@ ret_value program::show_error(ret_value err, const char* context) {
|
|||
}
|
||||
|
||||
/// @brief set the last error as being a syntax error and show it
|
||||
///
|
||||
///
|
||||
/// @param err the error to record
|
||||
/// @param context a context string
|
||||
/// @return ret_value see this type
|
||||
|
@ -617,14 +623,14 @@ void program::show_syntax_error(const char* context) {
|
|||
}
|
||||
|
||||
/// @brief return the last error set
|
||||
///
|
||||
///
|
||||
/// @return ret_value see this type
|
||||
///
|
||||
ret_value program::get_err(void) { return _err; }
|
||||
|
||||
/// @brief show a stack (show its different objects)
|
||||
/// generally a stack is associated to a running program
|
||||
///
|
||||
///
|
||||
/// @param st the stack to show
|
||||
/// @param show_separator whether to show a stack level prefix or not
|
||||
///
|
||||
|
|
|
@ -273,6 +273,11 @@ class program : public stack {
|
|||
void rpn_acos(void);
|
||||
void rpn_tan(void);
|
||||
void rpn_atan(void);
|
||||
|
||||
// time
|
||||
void rpn_time();
|
||||
void rpn_date();
|
||||
void rpn_ticks();
|
||||
};
|
||||
|
||||
// convinience macros for rpn_xx function
|
||||
|
|
73
src/rpn-time.cpp
Normal file
73
src/rpn-time.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include <time.h>
|
||||
#include "program.hpp"
|
||||
|
||||
/// @brief time keyword implementation
|
||||
///
|
||||
void program::rpn_time() {
|
||||
struct timespec ts;
|
||||
struct tm* tm;
|
||||
double date;
|
||||
|
||||
// get local date
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
time_t time = (time_t)ts.tv_sec;
|
||||
tm = localtime(&time);
|
||||
if (tm != NULL) {
|
||||
// date format = HH.MMSSssssss
|
||||
date = ((double)tm->tm_hour) * 10000000000.0 + ((double)tm->tm_min) * 100000000.0 +
|
||||
((double)tm->tm_sec) * 1000000.0 + (double)(ts.tv_nsec / 1000);
|
||||
|
||||
// push it
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd));
|
||||
// division is done here because of real precision)
|
||||
CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 10000000000.0, floating_t::s_mpfr_rnd));
|
||||
} else
|
||||
ERR_CONTEXT(ret_internal);
|
||||
}
|
||||
|
||||
/// @brief date keyword implementation
|
||||
///
|
||||
void program::rpn_date() {
|
||||
struct timespec ts;
|
||||
struct tm* tm;
|
||||
double date;
|
||||
|
||||
// get local date
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
time_t time = (time_t)ts.tv_sec;
|
||||
tm = localtime(&time);
|
||||
if (tm != NULL) {
|
||||
// date format = (M)M.DDYYYY
|
||||
date = (double)(tm->tm_mon + 1) * 1000000.0 + (double)(tm->tm_mday) * 10000.0 + (double)(tm->tm_year + 1900);
|
||||
|
||||
// push it
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd));
|
||||
// division is done here because of real precision)
|
||||
CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 1000000.0, floating_t::s_mpfr_rnd));
|
||||
} else
|
||||
ERR_CONTEXT(ret_internal);
|
||||
}
|
||||
|
||||
/// @brief ticks keyword implementation
|
||||
///
|
||||
void program::rpn_ticks() {
|
||||
struct timespec ts;
|
||||
struct tm* tm;
|
||||
double date;
|
||||
|
||||
// get local date
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
time_t time = (time_t)ts.tv_sec;
|
||||
tm = localtime(&time);
|
||||
if (tm != NULL) {
|
||||
// date in µs
|
||||
date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000);
|
||||
|
||||
// push it
|
||||
number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
|
||||
CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd));
|
||||
} else
|
||||
ERR_CONTEXT(ret_internal);
|
||||
}
|
25
test/12-time.txt
Normal file
25
test/12-time.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
## date and time
|
||||
default del
|
||||
|
||||
# date
|
||||
date type
|
||||
-> error should be 0
|
||||
-> stack should be "number"
|
||||
del
|
||||
|
||||
# time
|
||||
time type
|
||||
-> error should be 0
|
||||
-> stack should be "number"
|
||||
del
|
||||
|
||||
# ticks (1)
|
||||
ticks type
|
||||
-> error should be 0
|
||||
-> stack should be "number"
|
||||
del
|
||||
|
||||
# ticks (2)
|
||||
ticks ticks - 0 <=
|
||||
-> stack should be 1
|
||||
del
|
|
@ -9,4 +9,5 @@
|
|||
#include 09-program.txt
|
||||
#include 10-complex.txt
|
||||
#include 11-base-entry.txt
|
||||
#include 12-time.txt
|
||||
#include 99-manual-tests.txt
|
||||
|
|
Loading…
Reference in a new issue