A deeper introduction in Unix dc

Mandelbrot calculated with unix dc

The program

Unix dc is one of the oldest interpreter programs which is still available on most of the Linux distros without installing it. The program goes back to the PDP-11 era. The programming of it must be easier than any serious assembler or other kind of interpreters like BASIC, because it was sometimes earlier available [1, 2]. It moves the difficulty to code to the programmer.

DC stands for desk calculator and can be programmed in reverse-polish notation. It is stack oriented and supports arbitrary-precision. It has also registers, conditional statements and loops. These things are realised with macros saved in registers. Registers can only be single characters. It's really weird to program it.

Dc starts with the command dc on your terminal. There will be no welcome text, just a plain command line for you to get things done right now! You can try these code snippets also online with the JS Linux from bellard.org.

1. Variables

You can copy and paste the text or execute it from a file with dc -f file.dc.
# This is a comment.
# l for load s for save
1 sa
2 sb
3 sc

la lb + lc * p sd
Will print 9 and keeps it on the stack until it's saved to register d.

2. A conditional statement

# function f, prints chars and deletes the stack
[ [a is bigger then 10] p c] sf

# executes function f if a is bigger than 10

# nothing happens
8 sa
[la 10 <f] x

# function is called
11 sa
[la 10 <f] x

3. A for loop

# prints number 0 to 10
# d is duplicate, x execute
0 sa
[la p 1 + d sa 10 !<f] sf
lf x

# a faster way without a variable
[p 1 + d 10 !<f] sf
0 lf x

4. A loop in an inner loop

# xQ leaves macros to level x. 
# It's a termination condition for the recursive function. 
# The [A] p is never executed. 
# The st only removes the last variable from the stack. 

[p 1 + d 3 !<f st 4Q [A] p] sf

[1 + d d sa 0 lf x 3 !<g] sg

0
lg x
Edit: A even better, simpler solution:
[p 1 + d 3 !<f Q] sf

[1 + d d sa 0 lf x 3 !<g] sg

0
lg x

4. A multiplication table

1 sa
[la 1 sb lf x []pn d 1 + sa 10>g] sg
[lb d la * n [   ]n d 1 + sb 10>f] sf
lg x
It's not the nicest output:
1   2   3   4   5   6   7   8   9   10   
2   4   6   8   10   12   14   16   18   20   
3   6   9   12   15   18   21   24   27   30   
4   8   12   16   20   24   28   32   36   40   
5   10   15   20   25   30   35   40   45   50   
6   12   18   24   30   36   42   48   54   60   
7   14   21   28   35   42   49   56   63   70   
8   16   24   32   40   48   56   64   72   80   
9   18   27   36   45   54   63   72   81   90   
10   20   30   40   50   60   70   80   90   100

5. Mandelbrot set

File: mandelbrot.dc

This code is far away from beeing good. I'm happy it worked out at the end. I literally sacrificed some brain parts writing this.

Anyways, it creates an ASCII pattern which can be saved as a portable bitmap (PPM). With the conditions of 600x400 (row 6,7), a precision of 20 (row 2) and an iteration amount of 25 (row 28) you get following output.

dc -f mandelbrot.dc > mandelbrot.ppm
Mandelbrot PPM created with DC

Credits

08.06.2020
GitHub: ben165