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-stack.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-store.cpp
|
${PROJECT_SOURCE_DIR}/src/rpn-store.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/rpn-string.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.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}/src/rpn-trig.cpp
|
||||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
||||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
|
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
|
||||||
|
|
27
MANUAL.md
27
MANUAL.md
|
@ -128,8 +128,8 @@ rpn> 7b1252 dec
|
||||||
|keyword|description|
|
|keyword|description|
|
||||||
|-|-|
|
|-|-|
|
||||||
|`nop` | no operation
|
|`nop` | no operation
|
||||||
|`help\|h\|?` | this help message
|
|`help` `h` `?` | this help message
|
||||||
|`quit\|q\|exit` | quit software
|
|`quit` `q` `exit` | quit software
|
||||||
|`version` | show rpn version
|
|`version` | show rpn version
|
||||||
|`uname` | show rpn complete identification string
|
|`uname` | show rpn complete identification string
|
||||||
|`history`| see commands history
|
|`history`| see commands history
|
||||||
|
@ -140,13 +140,13 @@ rpn> 7b1252 dec
|
||||||
|-|-|
|
|-|-|
|
||||||
|`+`| addition
|
|`+`| addition
|
||||||
|`-`| substraction
|
|`-`| substraction
|
||||||
|`neg\|chs`| negation
|
|`neg` `chs`| negation
|
||||||
|`*`| multiplication
|
|`*`| multiplication
|
||||||
|`/`| division
|
|`/`| division
|
||||||
|`inv`| inverse
|
|`inv`| inverse
|
||||||
|`^\|pow`| power
|
|`^` `pow`| power
|
||||||
|`sqrt`| square root
|
|`sqrt`| square root
|
||||||
|`sq\|sqr`| square
|
|`sq` `sqr`| square
|
||||||
|`abs`| absolute value for a number or `sqrt(re*re+im*im)` for a complex
|
|`abs`| absolute value for a number or `sqrt(re*re+im*im)` for a complex
|
||||||
|`dec`| decimal representation
|
|`dec`| decimal representation
|
||||||
|`hex`| hexadecimal representation
|
|`hex`| hexadecimal representation
|
||||||
|
@ -220,7 +220,7 @@ rpn> 7b1252 dec
|
||||||
|`drop`| drop first stack entry
|
|`drop`| drop first stack entry
|
||||||
|`drop2`| drop 2 first stack entries
|
|`drop2`| drop 2 first stack entries
|
||||||
|`dropn`| drop n 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
|
|`rot`| rotate 3 first stack entries
|
||||||
|`dup`| duplicate first stack entry
|
|`dup`| duplicate first stack entry
|
||||||
|`dup2`| duplicate 2 first stack entries
|
|`dup2`| duplicate 2 first stack entries
|
||||||
|
@ -258,9 +258,9 @@ rpn> 7b1252 dec
|
||||||
|`next`| used with start and for
|
|`next`| used with start and for
|
||||||
|`step`| used with start and for
|
|`step`| used with start and for
|
||||||
|`do`| do (instructions) until (condition) end
|
|`do`| do (instructions) until (condition) end
|
||||||
|`until\|unti` | used with do
|
|`until` `unti` | used with do
|
||||||
|`while\|whil`| while (test-instruction) repeat (loop-instructions) end
|
|`while` `whil`| while (test-instruction) repeat (loop-instructions) end
|
||||||
|`repeat\|repea`| used with while
|
|`repeat` `repea`| used with while
|
||||||
|
|
||||||
### store
|
### store
|
||||||
|
|
||||||
|
@ -305,20 +305,23 @@ rpn> 7b1252 dec
|
||||||
|keyword|description|
|
|keyword|description|
|
||||||
|-|-|
|
|-|-|
|
||||||
|`e`| Euler constant
|
|`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
|
|`lnp1`| ln(1+x) which is useful when x is close to 0
|
||||||
|`exp`| exponential
|
|`exp`| exponential
|
||||||
|`expm`| exp(x)-1 which is useful when x is close to 0
|
|`expm`| exp(x)-1 which is useful when x is close to 0
|
||||||
|`log10`| logarithm base 10
|
|`log10`| logarithm base 10
|
||||||
|`alog10\|exp10`| exponential base 10
|
|`alog10` `exp10`| exponential base 10
|
||||||
|`log2`| logarithm base 2
|
|`log2`| logarithm base 2
|
||||||
|`alog2\|exp2`| exponential base 2
|
|`alog2` `exp2`| exponential base 2
|
||||||
|`sinh`| hyperbolic sine
|
|`sinh`| hyperbolic sine
|
||||||
|`asinh`| inverse hyperbolic sine
|
|`asinh`| inverse hyperbolic sine
|
||||||
|`cosh`| hyperbolic cosine
|
|`cosh`| hyperbolic cosine
|
||||||
|`acosh`| inverse hyperbolic cosine
|
|`acosh`| inverse hyperbolic cosine
|
||||||
|`tanh`| hyperbolic tangent
|
|`tanh`| hyperbolic tangent
|
||||||
|`atanh`| inverse 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
|
### default
|
||||||
|
|
||||||
|
|
36
README.md
36
README.md
|
@ -25,25 +25,31 @@ rpn> << -> x y << x y + ln >> >> 'P' sto
|
||||||
### and a bunch of functions
|
### and a bunch of functions
|
||||||
```
|
```
|
||||||
rpn>
|
rpn>
|
||||||
Display all 147 possibilities? (y or n)
|
Display all 150 possibilities? (y or n)
|
||||||
nop chs bin min prec not depth else repeat sinv ln cosh
|
nop pow fp >= dupn next sto* exp
|
||||||
help neg base max round same roll end repea eval log acosh
|
help sqrt min < pick step sto/ expm
|
||||||
h * sign re default swap rolld start sto -> lnp1 tanh
|
h sq max <= depth ift sneg log10
|
||||||
? / % im type drop over for rcl pi exp atanh
|
? sqr re != roll ifte sinv alog10
|
||||||
quit inv %CH conj > drop2 ->str next purge sin expm
|
quit abs im == rolld do eval exp10
|
||||||
q ^ mod arg >= dropn str-> step vars asin log10
|
q dec conj and over until -> log2
|
||||||
exit pow fact c->r < del chr ift clusr cos alog10
|
exit hex arg or ->str unti pi alog2
|
||||||
test sqrt mant r->c <= erase num ifte edit acos exp10
|
test bin c->r xor str-> while sin exp2
|
||||||
version sq xpon p->r != rot size do sto+ tan log2
|
version base r->c not chr whil asin sinh
|
||||||
uname sqr floor r->p == dup pos until sto- atan alog2
|
uname sign p->r same num repeat cos asinh
|
||||||
history abs ceil std and dup2 sub unti sto* d->r exp2
|
history % r->p swap size repea acos cosh
|
||||||
+ dec ip fix or dupn if while sto/ r->d sinh
|
+ %CH std drop pos sto tan acosh
|
||||||
- hex fp sci xor pick then whil sneg e asinh
|
- 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
|
## 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
|
## Manual
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ void program::entry_completion_generator(const char* text, linenoiseCompletions*
|
||||||
int text_len = strnlen(text, 6);
|
int text_len = strnlen(text, 6);
|
||||||
|
|
||||||
// propose all keywords
|
// propose all keywords
|
||||||
if (text_len == 0) {
|
if (text_len == 0) {
|
||||||
while (program::s_keywords[i].type != cmd_max) {
|
while (program::s_keywords[i].type != cmd_max) {
|
||||||
if (program::s_keywords[i].fn != NULL)
|
if (program::s_keywords[i].fn != NULL)
|
||||||
// add all keywords
|
// add all keywords
|
||||||
|
|
|
@ -202,12 +202,18 @@ program::keyword_t program::s_keywords[] = {
|
||||||
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
||||||
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse 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
|
// end
|
||||||
{cmd_max, "", NULL, ""},
|
{cmd_max, "", NULL, ""},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief run a program on a stack and a heap
|
/// @brief run a program on a stack and a heap
|
||||||
///
|
///
|
||||||
/// @param stk the stack, storing prog result
|
/// @param stk the stack, storing prog result
|
||||||
/// @param hp the heap, storing variables
|
/// @param hp the heap, storing variables
|
||||||
/// @return ret_value see this type
|
/// @return ret_value see this type
|
||||||
|
@ -305,12 +311,12 @@ ret_value program::run(stack& stk, heap& hp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief stop a program
|
/// @brief stop a program
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
void program::stop() { interrupt_now = true; }
|
void program::stop() { interrupt_now = true; }
|
||||||
|
|
||||||
/// @brief return whether a branch object has a given name
|
/// @brief return whether a branch object has a given name
|
||||||
///
|
///
|
||||||
/// @param b the branch object
|
/// @param b the branch object
|
||||||
/// @param str_to_compare the name
|
/// @param str_to_compare the name
|
||||||
/// @param len the name length
|
/// @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
|
/// this is needed before a program can be run
|
||||||
/// inner members of branch or keyword objects are filled by this function
|
/// 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.
|
/// these inner members store for example the index of the next keyword to execute etc.
|
||||||
///
|
///
|
||||||
/// @return ret_value see this type
|
/// @return ret_value see this type
|
||||||
///
|
///
|
||||||
ret_value program::preprocess(void) {
|
ret_value program::preprocess(void) {
|
||||||
|
@ -558,7 +564,7 @@ ret_value program::preprocess(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief show the last error set
|
/// @brief show the last error set
|
||||||
///
|
///
|
||||||
/// @return ret_value see this type
|
/// @return ret_value see this type
|
||||||
///
|
///
|
||||||
ret_value program::show_error() {
|
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
|
/// @brief record an error as the last error set and show it
|
||||||
///
|
///
|
||||||
/// @param err the error to record
|
/// @param err the error to record
|
||||||
/// @param context a context string
|
/// @param context a context string
|
||||||
/// @return ret_value see this type
|
/// @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
|
/// @brief record an error as the last error set and show it
|
||||||
///
|
///
|
||||||
/// @param err the error to record
|
/// @param err the error to record
|
||||||
/// @param context a context string
|
/// @param context a context string
|
||||||
/// @return ret_value see this type
|
/// @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
|
/// @brief set the last error as being a syntax error and show it
|
||||||
///
|
///
|
||||||
/// @param err the error to record
|
/// @param err the error to record
|
||||||
/// @param context a context string
|
/// @param context a context string
|
||||||
/// @return ret_value see this type
|
/// @return ret_value see this type
|
||||||
|
@ -617,14 +623,14 @@ void program::show_syntax_error(const char* context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief return the last error set
|
/// @brief return the last error set
|
||||||
///
|
///
|
||||||
/// @return ret_value see this type
|
/// @return ret_value see this type
|
||||||
///
|
///
|
||||||
ret_value program::get_err(void) { return _err; }
|
ret_value program::get_err(void) { return _err; }
|
||||||
|
|
||||||
/// @brief show a stack (show its different objects)
|
/// @brief show a stack (show its different objects)
|
||||||
/// generally a stack is associated to a running program
|
/// generally a stack is associated to a running program
|
||||||
///
|
///
|
||||||
/// @param st the stack to show
|
/// @param st the stack to show
|
||||||
/// @param show_separator whether to show a stack level prefix or not
|
/// @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_acos(void);
|
||||||
void rpn_tan(void);
|
void rpn_tan(void);
|
||||||
void rpn_atan(void);
|
void rpn_atan(void);
|
||||||
|
|
||||||
|
// time
|
||||||
|
void rpn_time();
|
||||||
|
void rpn_date();
|
||||||
|
void rpn_ticks();
|
||||||
};
|
};
|
||||||
|
|
||||||
// convinience macros for rpn_xx function
|
// 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 09-program.txt
|
||||||
#include 10-complex.txt
|
#include 10-complex.txt
|
||||||
#include 11-base-entry.txt
|
#include 11-base-entry.txt
|
||||||
|
#include 12-time.txt
|
||||||
#include 99-manual-tests.txt
|
#include 99-manual-tests.txt
|
||||||
|
|
Loading…
Reference in a new issue