Go to file
Marco Cetica 25569557ca
All checks were successful
dc / build (push) Successful in 50s
Fixed a bug related to modulo precision
2024-09-09 10:11:06 +02:00
.gitea/workflows Improved code 2024-03-13 09:15:33 +01:00
.github/workflows Improved code 2024-03-13 09:15:33 +01:00
bin New stable release(v1.0.6) 2024-04-19 16:34:57 +02:00
src Fixed a bug related to modulo precision 2024-09-09 10:11:06 +02:00
tests Added compiler information and fixed test on arm64 2024-09-06 10:49:59 +02:00
.gitignore Added documentation for Mathematics and Eval classes 2024-09-02 16:08:12 +02:00
CMakeLists.txt Added compiler information and fixed test on arm64 2024-09-06 10:49:59 +02:00
doc.md Added doxygen documentation 2024-09-04 16:21:07 +02:00
Doxyfile Added doxygen documentation 2024-09-04 16:21:07 +02:00
LICENSE First upload 2023-11-02 17:25:24 +01:00
main.cpp Added compiler information and fixed test on arm64 2024-09-06 10:49:59 +02:00
man.md Added doxygen documentation 2024-09-04 16:21:07 +02:00
README.md Updated README.md 2024-09-04 16:27:50 +02:00
utest.sh Added tests for 'math' class 2024-02-28 16:17:43 +01:00

dc CodeFactor

dc is an advanced, scientific and extensible RPN desktop calculator and a stack-based programming language (re)written in C++. By default, dc supports a wide range of arithmetical, trigonometrical and numeric functions and its capabilities can be further extended by writing user-defined programs using the embedded, turing-complete, macro system.

dc reads from the standard input, but it can also work with text files using the -f flag. Furthermore, you can decide to evaluate an expression without opening the REPL by using the -e flag.

Operands are pushed onto the stack following the LIFO policy; operators, on the other hand, pop one or more values from the stack and push back the result. By default, dc is very quiet, in order to inquiry the stack you need to use one of the supported options(see below).

dc can be invoked with the following command line options:

RPN desktop calculator and stack-based programming language. Usage: 
-e, --expression <EXPRESSION> | Evaluate an expression
-f, --file <FILE>             | Evaluate a file
-h, --help                    | Show this helper
-V, --version                 | Show version

Some of the supported features are:

  • Basic arithmetical operations(+, -, *, /, ^, %);
  • Scientific notation support(5e3 -> 5000);
  • Support for complex numbers(-1 v -> (0,1));
  • Trigonometrical functions(sin, cos, tan, asin, acos, atan);
  • Base-10 logarithm(y);
  • Statistical functions(permutations, combinations, summation, sum of squares, mean, standard deviation, linear regression);
  • Base conversion(binary: pb, octal: po, hexadecimal: px);
  • Factorial and constants(!, pi, e);
  • Random number generator(@);
  • Integer conversion($);
  • Bitwise operations({, }, l, L, m, M);
  • Stack operations:
    • Print top element(p, P, p.);
    • Clear the stack(c);
    • Remove top element(R);
    • Swap order of top two elements(r);
    • Duplicate top element(d);
    • Dump the whole stack(f);
    • Last head, 2nd, 3rd element of the stack(.x, .y, .z);
  • Parameters:
    • Set precision(k);
    • Set input and output radix(i and o);
  • Registers:
    • Store top element of the stack on register X(sX or SX);
    • Load content of register X on top of the stack(lX or LX);
  • Arrays:
    • Store second-to-top of main stack into array X indexed by top-of-stack(:X);
    • Pop top-of-stack and use it as an index for array X(;X);
  • Macros:
    • Define a new macro inside square brackets([ ]);
    • Executing a macro from the stack(x);
    • Evaluate a macro by comparing top-of-head and second-of-head elements(>X, <X, >=X, <=X, != where X is a register);
    • Load external file(').

And much more. You can find the complete manual here.

Installation

dc is written in C++20 without using any additional dependency. In order to build it, install CMake, Ninja and issue the following commands:

$> cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release .
$> cmake --build build

A new statically-compiled binary called dc will be created in the build/ directory. To generate a man page from the man.md document, use the following command(note: needs pandoc):

$> pandoc man.md -s -t man > dc.1

Otherwise, if you are running a Linux-based distribution, issue one of the following commands:

Debian/Ubuntu:

$> sudo apt install ./dc-<VERSION>.x86_64.deb

RHEL/Centos/Fedora

$> sudo dnf install ./dc-<VERSION>.x86_64.rpm

Arch

$> sudo pacman -U dc-<VERSION>-1-x86_64.pkg.tar.zst

You can find the binaries on the release page or on the bin folder of this repository.

Unit tests

This repository as well as the CI pipeline provides unit tests for the program's features. To run them, issue the following command:

$> ./utest.sh tests

Documentation

General purpose documentation about the program can be found at the online manual page or at the UNIX dc(1) man page. If you want to understand the source code of the program, you can read the technical documentation by issuing the following commands:

$> doxygen Doxyfile
$> open docs/html/index.html

The technical manual will appear on your browser.

Usage

dc can be used in three different ways:

  1. From the interactive REPL(run it without any argument);
  2. By evaluating an inline expression, i.e.
    $> dc -e "5 5 + p"
    
  3. By evaluating a text file, i.e.
    $> cat foo
    2 4 - # Evaluate 2 - 4
    2 ^   # Evaluate x^2
    p     # Print the result(4)
    $> dc -f foo
    4
    

Below there are more examples.

  1. Evaluate
\frac{-5 + \sqrt(25 - 16)}{2}
-5 25 16 - v + 2 / p

where v is the square root function

  1. Evaluate
\frac{.5 + .9}{3^4}
.5 .9 + 3 4 ^ / p
  1. Evaluate 10 + 5 inline(i.e. without opening the REPL):
$> dc -e "10 5 +"
  1. Evaluate an expression from a file:
$> cat foo
    5 5 + 
    2 d * v 
    f
$> dc -f ./foo
  1. Evaluate
\sin(2\pi) + \cos(2\pi)
2 pi * sin 2 pi * cos + p
  1. Swap top two elements using registers(you can also use the r command):
5 4 p # Load some values on the stack(output: 4)
sA sB # Pop values and store them into the registers 'A' and 'B'
lA lB # Push 'A' and 'B' content onto the stack
p     # Print top element(output: 5)
  1. Recall last value of top three elements of the stack:
10 1 / # <- Wrong operation: division instead of sum
.y     # Call last value of y register
.x     # Call last value of x register
+ p    # Sum and print head(output: 11)
  1. Print out numbers from 1 through user-defined upper bound:
[ p 1 + d lN >L ] sL # Print numbers from 1 through 'N'

[ Enter limit: ] P # Ask user for limit 'N'
? 1 + sN # Read from stdin
c 1 lL x # Clear the stack, add lower bound, load and execute macro
  1. Sum the first 36 natural numbers(😈), i.e.,
\sum_{i=1}^{37} i = 666
$> dc -e "36 [ d 1 - d 1 <F + ] d sF x p"
  1. Print the first 20 values of n!:
[ la 1 + d sa * p la 20 >y ] sy
0 sa 1
ly x
  1. Compute the factorial of a given number:
[ ln 1 - sn ln la * sa ln 1 !=f ] sf
[ Enter value: ] P ? sn
ln sa
lf x
la p
  1. Compute the sum 8AB6F + B783E in base 16. Print the result in base 10 and in base 2:
16 i
8AB6F B783E +
[ Result in base 10: ] P R p
[ Result in base 2: ] P R pb
  1. Compute the Greatest Common Divisor(GCD) between two user-defined numbers A and B:
[ Enter A: ] P R ?
[ Enter B: ] P R ?
[ d Sa r La % d 0 <a ] d sa x +
[ GCD(A,B)= ] P R p
  1. Compute the Least Common Multiple(LCM) between two user-defined numbers A and B:
[ Enter A: ] P R ? d sA
[ Enter B: ] P R ? d SA
[ d Sa r La % d 0 <a ] d sa x +
LA lA * r /
[ LCM(A,B)= ] P R p
  1. Find the roots of a quadratic equation of the form:
ax^2 + bx + c = 0

with $$a,b,c \in \mathbb{R}, a \neq 0$$

using the formula

x_{1,2} = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
#!/usr/local/bin/dc -f
# GIVEN A QUADRATIC EQUATION OF THE FORM
# AX^2 + BX + C = 0
# COMPUTE ITS REAL OR COMPLEX ROOTS
# DEVELOPED BY MARCO CETICA 2023
#
3 k
[ Enter A: ] P ? sA
[ Enter B: ] P ? sB
[ Enter C: ] P ? sC
lB 2 ^ 4 lA lC * * - v sD
lB -1 * lD - lA # NEGATIVE DELTA
2 * / sS # FIRST SOLUTION
lB -1 * lD + lA # POSITIVE DELTA
2 * / SS # SECOND SOLUTION
[ X1: ] P R lS p
[ X2: ] P R LS lS p
  1. Generate n (pseudo)random numbers from user-defined range:
5 k
[ lA lB @ p ] sR
[ Enter number of samples: ] P ? sN
[ Enter lower bound: ] P ? sA
[ Enter upper bound: ] P ? sB
[ lR x r 1 + d lN >=L ] sL
0 lL x
  1. Estimate \pi using Monte Carlo simulation:
10 k
[ 0 1 @ sX 0 1 @ sY ] sR
[ lX 2 ^ sX lY 2 ^ sY ] sQ
[ 0 ;A 1 + 0 :A ] sI
[ 1 lX lY + <=I ] sC
[ lR x lQ x lC x 1 + d lN >=L ] sL
0 0 :A
0 6500 sN
lL x 0 ;A lN /
4 * p
  1. Convert a hex color to RGB:
16 i
[ Enter hex value: ] P R ? sV
lV FF { 0 :A # Blue
lV 8 M FF { 1 :A # Green
lV 10 M FF { 2 :A # Red
[ , ] sc
[ [ RGB( ] P 2 ;A P lc p. 1 ;A P lc p. 0 ;A P [ ) ] p. [ = ] p. lV ph ] x
  1. Find the mean of the following temperatures(Celsius): [25, 15, 9.5, 10, 20, 16, 20]:
4 k
25 15 9.5 10 20 16 20
SX SX SX  SX SX SX SX
gM p # Prints 16.5000

License

GPLv3