diff --git a/MANUAL.md b/MANUAL.md index 7e62270..ba9f0d6 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -1,44 +1,39 @@ # **rpn** - reference manual **rpn** -- is a structured full-featured **math-oriented language** inspired by Hewlett-Packard **R**everse **P**olish **L**isp (**HP28S** and **HP48GX** user manuals are provided as references), including **real**, **complex**, **stack**, **store**, **branch**, **program**, **test**, **trig** and **logs** commands and more to come -- is implemented as a **command-line calculator** for most popular Linux distributions +- is a structured full-featured **math-oriented language** inspired by Hewlett-Packard **R**everse **P**olish **L**isp (**HP28S** and **HP48GX** user manuals are provided as references), including **real**, **complex**, **stack**, **store**, **branch**, **program**, **test**, **trig** and **logs** commands and more to come, +- is implemented as a **command-line calculator**, - brings powerfull calculation facilities on floating point numbers with __arbitrary precision__ provided by **GNU MP** and **GNU MPFR** libraries -- uses that so cool **reverse polish notation** +- uses that so cool **reverse polish notation**. ## Doc overview This page gives some examples and lists the commands currently implemented. -For a most complete help, please refer to HP28S and HP48GX manuals provided in the sources +For a most complete help, please refer to HP28S and HP48GX manuals provided in the sources. A help command is provided by rpn: -``` +```rpn rpn> help -rpn v2.4.0, (c) 2022 , GNU LGPL v3 - -Reverse Polish Notation language - -using GMP v6.1.2 under GNU LGPL -MPFR v4.0.1 under GNU LGPL -and linenoise-ng v1.0.0 under BSD - +rpn v2.4.0, (c) 2022 +Reverse Polish Notation CLI calculator Syntax: rpn [command] with optional command = list of commands - + GENERAL -nop no operation -help this help message +nop no operation +help this help message (...) ``` ## Quick examples -### easy calculation with **stacked results** -``` +### Easy calculation with **stacked results** + +```rpn rpn> 1 2 + 3 rpn> 2 sqrt @@ -46,9 +41,9 @@ rpn> 2 sqrt 1> 1.4142135623730950488016887242096980786 ``` -### **programs** and **variables** +### **Programs** and **variables** -``` +```rpn rpn> << rot * swap 2 / neg dup sq rot - sqrt >> 'quadratic_solution' sto rpn> 1 2 -3 quadratic_solution 2> -1 @@ -57,17 +52,19 @@ rpn> vars var 1: name 'quadratic_solution', type program, value << rot * swap 2 / chs dup sq rot - sqrt >> ``` -### **local variables** -``` +### **Local variables** + +```rpn rpn> << -> x y << x y + ln >> >> 'P' sto rpn> 1 2 P rpn> 1.0986122886681096913952452369225257046 ``` -### **arbitrary precision** +### **Arbitrary precision** + The number of significant digits can be very large thanks to GNU MPFR -``` +```rpn rpn> 256 prec rpn> pi 3.1415926535897932384626433832795028841971693993751058209749445923078164062862 @@ -76,10 +73,11 @@ rpn> erase 10000 prec pi rpn> ``` -### object types +### Object types The following objects are managed: **floating numbers**, **complexes**, **symbols**, **strings**, **programs**, plus language **keywords** (commands and flow controls). -``` + +```rpn 5> 12.3456 4> (1,-2.33) 3> 'symbol' @@ -106,9 +104,9 @@ Autocompletion works like those in Linux shells, with keys \, Ctrl-R \b`. - Representation can be individualy changed with keywords `dec`, `bin`, `hex` and ` base`. - ex: -``` + +```rpn rpn> 5.6 0xaabb 0b1101 7b1252 4> 5.6 3> 0xaabb @@ -123,203 +121,204 @@ rpn> 7b1252 dec ### general -|keyword|description| -|-|-| -|`nop` | no operation -|`help` `h` `?` | this help message -|`quit` `q` `exit` | quit software -|`version` | show rpn version -|`uname` | show rpn complete identification string -|`history`| see commands history +| keyword | description | +|-------------------|-----------------------------------------| +| `nop` | no operation | +| `help` `h` `?` | this help message | +| `quit` `q` `exit` | quit software | +| `version` | show rpn version | +| `uname` | show rpn complete identification string | +| `history` | see commands history | ### usual operations - real and complex -|keyword|description| -|-|-| -|`+`| addition -|`-`| substraction -|`neg` `chs`| negation -|`*`| multiplication -|`/`| division -|`inv`| inverse -|`^` `pow`| power -|`sqrt`| square root -|`sq` `sqr`| square -|`abs`| absolute value for a number or `sqrt(re*re+im*im)` for a complex -|`dec`| decimal representation -|`hex`| hexadecimal representation -|`bin`| binary representation -|`base`| arbitrary base representation -|`sign`| sign of a real, unary vector in the same direction for a complex +| keyword | description | +|-------------|------------------------------------------------------------------| +| `+` | addition | +| `-` | substraction | +| `neg` `chs` | negation | +| `*` | multiplication | +| `/` | division | +| `inv` | inverse | +| `^` `pow` | power | +| `sqrt` | square root | +| `sq` `sqr` | square | +| `abs` | absolute value for a number or `sqrt(re*re+im*im)` for a complex | +| `dec` | decimal representation | +| `hex` | hexadecimal representation | +| `bin` | binary representation | +| `base` | arbitrary base representation | +| `sign` | sign of a real, unary vector in the same direction for a complex | ### operations on reals -|keyword|description| -|-|-| -|`%`| purcent -|`%CH`| inverse purcent -|`mod`| modulo -|`fact`| n! for integer n or Gamma(x+1) for fractional x -|`mant`| mantissa of a real number -|`xpon`| exponant of a real number -|`floor`| largest number <= -|`ceil`| smallest number >= -|`ip`| integer part -|`fp`| fractional part -|`min`| min of 2 real numbers -|`max`| max of 2 real numbers +| keyword | description | +|---------|-------------------------------------------------| +| `%` | purcent | +| `%CH` | inverse purcent | +| `mod` | modulo | +| `fact` | n! for integer n or Gamma(x+1) for fractional x | +| `mant` | mantissa of a real number | +| `xpon` | exponant of a real number | +| `floor` | largest number <= | +| `ceil` | smallest number >= | +| `ip` | integer part | +| `fp` | fractional part | +| `min` | min of 2 real numbers | +| `max` | max of 2 real numbers | ### operations on complexes -|keyword|description| -|-|-| -|`re`| complex real part -|`im`| complex imaginary part -|`conj`| complex conjugate -|`arg`| complex argument in radians -|`r->p`| rectangular to polar coordinates -|`p->r`| polar to rectangular coordinates -|`r->c`| transform 2 reals in a complex -|`c->r`| transform a complex in 2 reals +| keyword | description | +|---------|----------------------------------| +| `re` | complex real part | +| `im` | complex imaginary part | +| `conj` | complex conjugate | +| `arg` | complex argument in radians | +| `r->p` | rectangular to polar coordinates | +| `p->r` | polar to rectangular coordinates | +| `r->c` | transform 2 reals in a complex | +| `c->r` | transform a complex in 2 reals | ### mode -|keyword|description| -|-|-| -|`std`| standard floating numbers representation. ex: `std` -|`fix`| fixed point representation. ex: `6 fix` -|`sci`| scientific floating point representation. ex: `20 sci` -|`prec`| set float precision in bits. ex: `256 prec` -|`round`| set float rounding mode. Authorized values are: `"nearest"` `"toward zero"` `"toward +inf"` `"toward -inf"` `"away from zero"`. ex: `"nearest" round` -|`default` | set float representation and precision to default -|`type` | show type of stack first entry +| keyword | description | +|-----------|------------------------------------------------------------------------------------------------------------------------------------| +| `std` | standard floating numbers representation. ex: `std` | +| `fix` | fixed point representation. ex: `6 fix` | +| `sci` | scientific floating point representation. ex: `20 sci` | +| `prec` | set float precision in bits. ex: `256 prec` | +| `round` | set float rounding mode. Authorized values are: | +| | `"nearest (even)", "toward zero", "toward +inf", "toward -inf", "away from zero", "faithful rounding", "nearest (away from zero)"` | +| `default` | set float representation and precision to default | +| `type` | show type of stack first entry | ### test -|keyword|description| -|-|-| -|`>`| binary operator > -|`>=`| binary operator >= -|`<`| binary operator < -|`<=`| binary operator <= -|`!=`| binary operator != (different) -|`==`| binary operator == (equal) -|`and`| boolean operator and -|`or`| boolean operator or -|`xor`| boolean operator xor -|`not`| boolean operator not -|`same`| boolean operator same (equal) +| keyword | description | +|---------|--------------------------------| +| `>` | binary operator > | +| `>=` | binary operator >= | +| `<` | binary operator < | +| `<=` | binary operator <= | +| `!=` | binary operator != (different) | +| `==` | binary operator == (equal) | +| `and` | boolean operator and | +| `or` | boolean operator or | +| `xor` | boolean operator xor | +| `not` | boolean operator not | +| `same` | boolean operator same (equal) | ### stack -|keyword|description| -|-|-| -|`swap`| swap 2 first stack entries -|`drop`| drop first stack entry -|`drop2`| drop 2 first stack entries -|`dropn`| drop n first 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 -|`dupn`| duplicate n first stack entries -|`pick`| push a copy of the given stack level onto the stack -|`depth`| give stack depth -|`roll`| move a stack entry to the top of the stack -|`rolld`| move the element on top of the stack to a higher stack position -|`over`| push a copy of the element in stack level 2 onto the stack +| keyword | description | +|---------------|-----------------------------------------------------------------| +| `swap` | swap 2 first stack entries | +| `drop` | drop first stack entry | +| `drop2` | drop 2 first stack entries | +| `dropn` | drop n first 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 | +| `dupn` | duplicate n first stack entries | +| `pick` | push a copy of the given stack level onto the stack | +| `depth` | give stack depth | +| `roll` | move a stack entry to the top of the stack | +| `rolld` | move the element on top of the stack to a higher stack position | +| `over` | push a copy of the element in stack level 2 onto the stack | ### string -|keyword|description| -|-|-| -|`->str`| convert an object into a string -|`str->`| convert a string into an object -|`chr`| convert ASCII character code in stack level 1 into a string -|`num`| return ASCII code of the first character of the string in stack level 1 as a real number -|`size`| return the length of the string -|`pos`| seach for the string in level 1 within the string in level 2 -|`sub`| return a substring of the string in level 3 +| keyword | description | +|---------|------------------------------------------------------------------------------------------| +| `->str` | convert an object into a string | +| `str->` | convert a string into an object | +| `chr` | convert ASCII character code in stack level 1 into a string | +| `num` | return ASCII code of the first character of the string in stack level 1 as a real number | +| `size` | return the length of the string | +| `pos` | seach for the string in level 1 within the string in level 2 | +| `sub` | return a substring of the string in level 3 | ### branch -|keyword|description| -|-|-| -|`if`| `(test-instruction) if then (true-instructions) else (false-instructions) end` -|`then`| used with if -|`else`| used with if -|`end`| used with various branch instructions -|`ift`| similar to if-then-end: `(test-instruction) (true-instruction) ift` -|`ifte`| similar to if-then-else-end: `(test-instruction) (true-instruction) (false-instruction) ifte` -|`start`| `(start) (end) start (instructions) [next,(step) step]`. ex: `10 20 30 1 2 start + next` -|`for`| `(start) (end) for (variable) (instructions) [next,(step) step]`. ex: `1 2 for i i 'a' sto+ 0.1 step` -|`next`| used with start and for -|`step`| used with start and for -|`do`| `do (instructions) until (condition) end` -|`until` | used with do -|`while` | `while (test-instruction) repeat (loop-instructions) end` -|`repeat` | used with while +| keyword | description | +|----------|-------------------------------------------------------------------------------------------------------| +| `if` | `(test-instruction) if then (true-instructions) else (false-instructions) end` | +| `then` | used with if | +| `else` | used with if | +| `end` | used with various branch instructions | +| `ift` | similar to if-then-end: `(test-instruction) (true-instruction) ift` | +| `ifte` | similar to if-then-else-end: `(test-instruction) (true-instruction) (false-instruction) ifte` | +| `start` | `(start) (end) start (instructions) [next,(step) step]`. ex: `10 20 30 1 2 start + next` | +| `for` | `(start) (end) for (variable) (instructions) [next,(step) step]`. ex: `1 2 for i i 'a' sto+ 0.1 step` | +| `next` | used with start and for | +| `step` | used with start and for | +| `do` | `do (instructions) until (condition) end` | +| `until` | used with do | +| `while` | `while (test-instruction) repeat (loop-instructions) end` | +| `repeat` | used with while | ### store -|keyword|description| -|-|-| -|`sto`| store a variable. ex: ```1 'name' sto``` -|`rcl`| recall a variable. ex: ```'name' rcl``` -|`purge`| delete a variable. ex: ```'name' purge``` -|`vars`| list all variables -|`clusr`| erase all variables -|`edit`| edit a variable content -|`sto+`| add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+ -|`sto-`| substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto- -|`sto*`| multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto* -|`sto/`| divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/ -|`sneg`| negate a variable. ex: 'name' sneg -|`sinv`| inverse a variable. ex: 1 'name' sinv +| keyword | description | +|---------|-----------------------------------------------------------------| +| `sto` | store a variable. ex: ```1 'name' sto``` | +| `rcl` | recall a variable. ex: ```'name' rcl``` | +| `purge` | delete a variable. ex: ```'name' purge``` | +| `vars` | list all variables | +| `clusr` | erase all variables | +| `edit` | edit a variable content | +| `sto+` | add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+ | +| `sto-` | substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto- | +| `sto*` | multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto* | +| `sto/` | divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/ | +| `sneg` | negate a variable. ex: 'name' sneg | +| `sinv` | inverse a variable. ex: 1 'name' sinv | ### program -|keyword|description| -|-|-| -|`eval`| evaluate (run) a program, or recall a variable. ex: `'my_prog' eval` -|`->`| load program local variables. ex: `<< -> n m << 0 n m for i i + next >> >>` +| keyword | description | +|---------|-----------------------------------------------------------------------------| +| `eval` | evaluate (run) a program, or recall a variable. ex: `'my_prog' eval` | +| `->` | load program local variables. ex: `<< -> n m << 0 n m for i i + next >> >>` | ### trig on reals and complexes -|keyword|description| -|-|-| -|`pi`| pi constant -|`sin`| sinus -|`asin`| arg sinus -|`cos`| cosinus -|`acos`| arg cosinus -|`tan`| tangent -|`atan`| arg tangent -|`d->r`| convert degrees to radians -|`r->d`| convert radians to degrees +| keyword | description | +|---------|----------------------------| +| `pi` | pi constant | +| `sin` | sinus | +| `asin` | arg sinus | +| `cos` | cosinus | +| `acos` | arg cosinus | +| `tan` | tangent | +| `atan` | arg tangent | +| `d->r` | convert degrees to radians | +| `r->d` | convert radians to degrees | ### logs on reals and complexes -|keyword|description| -|-|-| -|`e`| Euler constant -|`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 -|`log2`| logarithm 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 +| keyword | description | +|------------------|-----------------------------------------------| +| `e` | Euler constant | +| `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 | +| `log2` | logarithm 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 @@ -331,46 +330,58 @@ Default rounding mode is 'nearest' ## Tests -- A set of complete test sheets are given in the [test](https://github.com/louisrubet/rpn/tree/master/test) subdirectory. Each version is fully tested before delivery +- A set of complete test sheets are given in the [test](https://github.com/louisrubet/rpn/tree/master/test) subdirectory. + +- All tests are run each at each pull on a pull request branch. Memory tests (`valgrind`) are also executed on each tests. - Test sheets syntax is - ``` - # cat my_test_sheet.txt + ```shell + cat my_test_sheet.md - ## Test sheet example - default erase + # Test sheet example + `default del` + + ## test step 1 + + `1 dup 1 +` - # test step 1 - 1 dup 1 + -> stack size should be 2 - -> stack should be 1, 2 - -> error should be 0 - erase - # test step 2 - 2 4 / 0.5 == + -> stack should be 1, 2 + + -> error should be 0 + + `del` + + ## test step 2 + + `2 4 / 0.5 ==` + -> stack should be 1 - erase + + `del` ``` - Test sheet can be played with the command `test` - ``` - rpn> "my_test_sheet.txt" - "my_test_sheet.txt" - rpn> test + ```rpn + rpn> "my_test_sheet.md" test + + rpn version is v2.3.2-68-g60099e3 + + my_test_sheet.md: Test sheet example + ## test step 1 PASSED + ## test step 2 PASSED + run 2 tests: 2 passed, 0 failed (4 steps: 4 passed, 0 failed) - my_test_sheet.txt: Test sheet example - # test step 1 PASSED - # test step 2 PASSED - my_test_sheet.txt: run 2 tests: 2 passed, 0 failed (4 steps: 4 passed, 0 failed) Total: run 2 tests: 2 passed, 0 failed (4 steps: 4 passed, 0 failed) rpn> ``` - Please follow these rules to write correct test sheets: - - make the test sheet begins by `default erase` + + - make the test sheet begins by `default del` - the 3 existing tests are `-> stack size should be (number)` `-> stack should be (values separated by commas)` `-> error should be (error number)` diff --git a/README.md b/README.md index 4b1b2c2..cdd27d7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # **rpn** - **R**everse **P**olish **N**otation CLI calculator [![License: LGPLv3](https://www.gnu.org/graphics/lgplv3-88x31.png)](https://www.gnu.org/licenses/lgpl-3.0.en.html) -A math functional language using reverse polish notation. - ### A math functional language using reverse polish notation ```rpn @@ -42,7 +40,7 @@ rpn> pi rpn> ``` -### Variables, strings, structured programming +### Variables, structured programming ```rpn rpn> « rot * swap 2 / chs dup sq rot - sqrt » 'quad' sto diff --git a/src/program.cc b/src/program.cc index df5f88e..e1e6eaf 100644 --- a/src/program.cc +++ b/src/program.cc @@ -69,9 +69,9 @@ vector program::keywords_{ {kKeyword, "sci", &program::RpnSci, "scientific floating point representation. ex: 20 sci"}, {kKeyword, "prec", &program::RpnPrecision, "set float precision in bits. ex: 256 prec"}, {kKeyword, "round", &program::RpnRound, - "set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward " - "+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"] round"}, - + "set float rounding mode in \n\t\"nearest (even)\", \"toward zero\", \"toward " + "+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"" + "\n\tex: \"nearest (even)\" round"}, {kKeyword, "default", &program::RpnDefault, "set float representation and precision to default"}, {kKeyword, "type", &program::RpnType, "show type of stack first entry"}, {kKeyword, "hex", &program::RpnHex, "hexadecimal representation, applies on stack level 0 only"},