aboutsummaryrefslogtreecommitdiff
path: root/doc/edc_src.1
blob: 4c33d412be8db844b25de7888d20f42e34d77572 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
.\" Copyright (C), 2023  Duncan Wilkie
.\" You may distribute this file under the terms of the GNU Free
.\" Documentation License.
.TH edc 1 2023-11-15
.ds edc \fIedc\fP
.ds Edc \fIedc\fP
.SH NAME
edc \- the exact desk calculator
.SH SYNOPSIS
edc [-?V] [-e scriptexpression] [-f script-file]
    [--expression=scriptexpression] [--file=script-file] [--help]
    [--usage] [--version] [file ...]
.SH DESCRIPTION
.PP
.B Edc
is a
.MR dc 1
style RPN calculator program, distinct in its use of
exact real arithmetic.
It uses IC-Reals, a set of C routines developed at Imperial College
that implement a system for performing exact (not arbitrary-precision)
computations with real numbers (Edalat and Heckmann 2002).
The distinction is subtle, but has significant consequences:
try computing the 100th term of the sequence

.EQ
a(0) = 11 / 2,
.EN

.EQ
a(1) = 61 / 11,
.EN

.EQ
 a(n) = 111 ^-^ (1130 ^-^ 3000 ^/^ a(n ^-^ 2)) ^/^ a(n ^-^ 1)
.EN

in Emacs calc, at precisions 5, 10, 30, 60, 100, 110, 120, 130, and 140.

.EX
;; Evaluate, and then: M-x calc RET p 5 RET 'hell(100) RET
;; etc.

(defmath hell (n)
  (let ((nm2 (/ :"11.0" :"2.0"))
        (nm1 (/ :"61.0" :"11.0"))
        (old 0))
    (for ((i 3 n))
      (setq old nm1)
      (setq nm1 (- 111
                   (/ (- 1130
                         (/ 3000
                            nm2))
                       nm1)))
      (setq nm2 old))
      nm1))
.EE

You get the results
.TS
box center;
Cb Cb
L C.
Precision	Estimate
5	100.
10	100.
30	100.
60	99.(9^57)7
100	100.0000000...
120	100.(0^31)3...
130	5.(9^7)83...
140	5.(9^7)85...
.TE

This sequence provably converges to 6.
And that should be scary; who would compute this to 130 digits of precision
if the value for 60 were so near to a round number?
Who would trust the result for 130 digits;
how could you tell it was more correct?
Maybe what caused this problem is worse with more digits.
Not only do you need to worry about the truncation error of the sequence,
but also the accumulated rounding error!
.PP
Exact real arithmetic avoids this problem via lazy precision.
Numbers are viewed as streams of (signed) digits
encoding chains of descending subsets, and when a computation returns,
the result truly must be within the indicated subset.
.PP
The
.B edc
incantation

.EX
[0:1 0:2 111 1130 3000 0;2 / - 0;1 / - 0;1 r]0:s
11/2 61/11 0;sx0;sx0;sx0;sx0;sx
.EE

gives approximately 5.75; computing further terms yields a sequence
that seems to monotonically approach 6.
If you repeat 0;sx 100 times (to compute the 100th term),
the result is 6 to within 2 in 10^8.
.PP
.B Edc
has very similar command syntax to its predecessor.
Some exceptions are:
.TP
.PP
Comparisons are ordered like a reasonable person would expect,
i.e. '1 2 <' corresponds to infix '1 < 2', just as '1 2 -'
corresponds to '1 - 2'.
.TP
.PP
There is no 'X' command; 'Z', in addition to producing
the number of digits of an integer and length of a string,
simply produces the number of currently-computed digits
of a real value.
.TP
.PP
There is no '!' command.
Enjoy the absence of shell-injection.
.TP
.PP
There are no decimal points, save in output:
real-valued input is provided through rational numbers.
Examples: '1/2', '2/1', '123412341234/987098709870987'.
Non-examples: '1 / 2', '12.7', '1/'.
Irrational and transcendentals must be accessed by commands.
This choice emphasizes the computable, non-floating-point nature
of the tool. (And, the real reason, was easier to implement.)
.TP
.PP
Comparisons take an extra integer argument, last on the stack: a precision.
They execute their macros only if the comparison is provably true
for the passed values computed to within the given precision.
As a special case, numbers are considered equal
if they are not provably not equal.
(Comparisons of integers are, by contrast, computable;
they have their usual meaning, and the precision is ignored.)
.TP
.PP
The 'P' command instead pushes pi onto the stack.
.TP
.PP
The 'n' command is renamed to 'm'.
.TP
.PP
There are additional commands for common constants and special functions.
.PD
.SH OPTIONS
.B Edc
may be invoked with the following command-line options:
.TP
.B -V
.TP
.B --version
Print out the version of
.B edc
that is being run and a copyright notice,
then exit.
.TP
.B -h
.TP
.B --help
Print a usage message briefly summarizing these command-line options
and the bug-reporting address,
then exit.
.TP
.B -e \fIscript\fP
.TP
.BI --expression= script
Add the commands in
.I script
to the set of commands to be run while processing the input.
.TP
.B -f \fIscript-file\fP
.TP
.BI --file= script-file
Add the commands contained in the file
.I script-file
to the set of commands to be run while processing the input.
.PP
If any command-line parameters remain after processing the above,
these parameters are interpreted as the names of input files
to be processed.
A file name of
.B -
refers to the standard input stream.
The standard input will be processed if no script files
or expressions are specified.
.PD
.SH Printing Commands
.TP
.B p
Prints the value on the top of the stack,
without altering the stack.
A newline is printed after the value.
.TP
.B n
Prints the value on the top of the stack, popping it off,
and does not print a newline after.
.TP
.B f
Prints the entire contents of the stack
.ig
and the contents of all of the registers,
..
without altering anything.
This is a good command to use if you are lost or want
to figure out what the effect of some command has been.
.PD
.SH Arithmetic
.TP
.B +
Pops two values off the stack, adds them,
and pushes the result.
.TP
.B -
Pops two values,
subtracts the first one popped from the second one popped,
and pushes the result.
.TP
.B *
Pops two values, multiplies them, and pushes the result.
.TP
.B /
Pops two values,
divides the second one popped from the first one popped,
and pushes the result.
Performs a C-style integer division if both arguments
are integers.
.TP
.B %
Pops two values,
computes the remainder of the division that the
.B /
command would do,
and pushes that.
The value computed is the same as that computed by
the sequence \fBSd dld/ Ld*-\fP by definition.
.TP
.B ~
Pops two values,
divides the second one popped from the first one popped.
The quotient is pushed first, and the remainder is pushed next.
The value is the same as \fBSdSn lnld/ LnLd%\fP
by definition.
.TP
.B ^
Pops two values and exponentiates,
using the first value popped as the exponent
and the second popped as the base.
.TP
.B |
Pops three values and computes a modular exponentiation.
The first value popped is used as the reduction modulus;
this value must be a non-zero number,
and should be an integer.
The second popped is used as the exponent;
this value must be a non-negative number,
and any fractional part of this exponent will be ignored.
The third value popped is the base which gets exponentiated,
which should be an integer.
For small integers this is like the sequence \fBSm^Lm%\fP,
but, unlike \fB^\fP, this command will work with arbitrarily large exponents.
.TP
.B v
Pops one value, computes its square root, and pushes that.
.PP
Real values are forced on printing; the
.B k
command sets the number of digits after the decimal point to print.
The default display precision value is 10.
.SH
Stack Control
.TP
.B c
Clears the stack, rendering it empty.
.TP
.B d
Duplicates the value on the top of the stack,
pushing another copy of it.
Thus, ``4d*p'' computes 4 squared and prints it.
.TP
.B r
Reverses the order of (swaps) the top two values on the stack.
.TP
.B R
Pops the top-of-stack as an integer
.IR n .
Cyclically rotates the top
.I n
items on the updated stack.
If
.I n
is positive, then the rotation direction will make the topmost
element the second-from top;
if
.I n
is negative, then the rotation will make the topmost element the
.IR n -th
element from the top.
If the stack depth is less than
.IR n ,
then the entire stack is rotated (in the appropriate direction),
without any error being reported.
.SH
Registers
.PP
.B Edc
provides 256 memory registers,
each named by a single character.
You can store a number or a string in a register and retrieve it later.
.TP
.BI s r
Pop the value off the top of the stack and store
it into register
.IR r .
.TP
.BI l r
Copy the value in register
.I r
and push it onto the stack.
The value 0 is retrieved if the register is uninitialized.
This does not alter the contents of
.IR r .
.PP
Each register also contains its own stack.
The current register value is the top of the register's stack.
.TP
.BI S r
Pop the value off the top of the (main) stack and
push it onto the stack of register
.IR r .
The previous value of the register becomes inaccessible.
.TP
.BI L r
Pop the value off the top of register
.IR r 's
stack and push it onto the main stack.
The previous value
in register
.IR r 's
stack, if any,
is now accessible via the
.BI l r
command.
.SH
Parameters
.PP
.B Edc
has three parameters that control its operation:
the display precision, the input radix, and the output radix.
The display precision specifies the number
of real digits after the decimal point to print.
The input radix controls the interpretation of numbers typed in;
all numbers typed in use this radix.
The output radix is used for printing integers
(all reals are output in decimal, as IC-Reals doesn't expose
anything that makes that easy).
Bases greater than 10 use as extra digits capital letters A through F;
just as with
.MR dc 1
the bases 2 through 16 are supported.
.PP
The input and output radices are separate parameters;
you can make them unequal,
which can be useful or confusing.
Each must be between 2 and 16 inclusive.
The output must be nonnegative.
.TP
.B i
Pops the value off the top of the stack
and uses it to set the input radix.
.TP
.B o
Pops the value off the top of the stack
and uses it to set the output radix.
.TP
.B k
Pops the value off the top of the stack
and uses it to set the precision.
.TP
.B I
Pushes the current input radix on the stack.
.TP
.B O
Pushes the current output radix on the stack.
.TP
.B K
Pushes the current precision on the stack.
.SH
Strings
.PP
.B Edc
has a limited ability to operate on strings
as well as on numbers;
the only things you can do with strings are
print them and execute them as macros
(which means that the contents of the string are processed as
.B edc
commands).
All registers and the stack can hold strings,
and
.B edc
always knows whether any given object is a string or a number.
Some commands such as arithmetic operations demand numbers
as arguments and print errors if given strings.
Other commands can accept either a number or a string;
for example, the
.B p
command can accept either and prints the object
according to its type.
.TP
.BI [ characters ]
Makes a string containing
.I characters
(contained between balanced
.B [
and
.B ]
characters),
and pushes it on the stack.
For example,
.B [foo]P
prints the characters
.B foo
(with no newline).
.TP
.B a
The top-of-stack is popped.
If it was an integer, then the low-order byte of this number
is converted into a string and pushed onto the stack.
If it was a string,
the first character of that string is pushed back.
If it is real, an error is signalled, as reals have
infinite digits.
.TP
.B x
Pops a value off the stack and executes it as a macro.
Normally it should be a string;
if it is a number,
it is simply pushed back onto the stack.
For example,
.B [1p]x
executes the macro
.B 1p
which pushes
.B 1
on the stack and prints
.B 1
on a separate line.
.PP
Macros are most often stored in registers;
.B [1p]sa
stores a macro to print
.B 1
into register
.BR a ,
and
.B lax
invokes this macro.
.TP
.BI > r
Pops three values off the stack and compares the lowest two,
assuming they are numbers, within the precision indicated by the topmost.
The contents of register
.I r
are executed as a macro if the lowest is provably greater
within the precision.
The precision is ignored if both are integers.
Thus,
.B 2 1 0>a
will invoke register
.BR a 's
contents and
.B 1 2 0>a
will not.
.TP
.BI !> r
Similar, but invokes the macro if the lowest is provably not greater
(less than or equal to) the second lowest.
.TP
.BI < r
Similar, but invokes the macro if the lowest is less
than the second lowest.
.TP
.BI !< r
Similar, but invokes the macro if the lowest is provably not less
(greater than or equal to) the second lowest.
.TP
.BI = r
Invokes invokes the macro if the two numbers popped
are not provably not equal,
i.e. if the intervals computed at the specified precision overlap.
.TP
.BI != r
Similar, but invokes the macro if the two numbers popped are
provably not equal, i.e. if the intervals computed
at the specified precision do not overlap.
.TP
.B ?
Reads a line from the terminal and executes it.
This command allows a macro to request input from the user.
.TP
.B q
exits from a macro and also from the macro which invoked it.
If called from the top level,
or from a macro which was called directly from the top level,
the
.B q
command will cause
.B edc
to exit.
.TP
.B Q
Pops a value off the stack and uses it as a count
of levels of macro execution to be exited.
Thus,
.B 3Q
exits three levels.
The
.B Q
command will never cause
.B edc
to exit.
.SH
Status Inquiry
.TP
.B Z
Pops a value off the stack,
calculates the number of decimal digits it has
(or number of characters, if it is a string)
and pushes that number.
The digit count for a number does
.I not
include any leading zeros,
even if those appear to the right of the radix point.
If the value is a real number,
it pushes the number of digits computed so far.
.TP
.B z
Pushes the current stack depth:
the number of objects on the stack before the execution of the
.B z
command.
.SH Edc Extensions
.TP
.B N
Pops a value off the stack,
pushing its negation.
.TP
.B M
Pops a value off the stack,
pushing its magnitude (absolute value).
.TP
.B e
Pops a value off the stack,
and pushes the exponential function of the result.
.TP
.B g
Pops a value off the stack,
and pushes the natural logarithm of the result.
.TP
.B t
Pops a value off the stack.
Interprets the next character (s(in), c(os),
t(an), S(ec), C(sc), (co)T)
as a trigonometric function,
pushing its result.
.TP
.B h
Pops a value off the stack.
Interprets the next character (s(inh), c(osh),
t(anh), S(ech), C(sch), (co)T(h))
as a hyperbolic trigonometric function,
pushing its result.
.TP
.B n
Pops a value off the stack.
Interprets the next two characters
as a trigonometric or hyperbolic trigonometric function,
pushing the result of the corresponding iNverse.
.TP
.B P
Pushes pi.
.TP
.B X
Pushes Euler's eXponential constant.
.SH
Miscellaneous
.TP
.B #
Will interpret the rest of the line as a comment.
.TP
.BI : r
Will pop the top two values off of the stack.
The old second-to-top value will be stored in the array
.IR r ,
indexed by the old top-of-stack value.
.TP
.BI ; r
Pops the top-of-stack and uses it as an index into
the array
.IR r .
The selected value is then pushed onto the stack.
.P
Note that each stacked instance of a register has its own
array associated with it.
Thus \fB1 0:a 0Sa 2 0:a La 0;ap\fP will print 1,
because the 2 was stored in an instance of 0:a that
was later popped.
.SH Errors
Quoting the libc manual, ``the experienced user will know
what is wrong.''
For the inexperienced:
.TP
.BI ? c
Unrecognized command
.IR c .
.TP
.B !-
Stack underflow.
.TP
.BI ! r -
Register
.IR r
stack underflow.
.TP
.B !+
Stack overflow.
.TP
.BI ! r +
Register
.IR r
stack overflow.
.TP
.B !?
Unsupported value.

Errors that cause the program to prematurely exit are bugs.
.SH BUGS
Email bug reports to
.B duncannwilkie@gmail.com
.SH AUTHOR
Duncan Wilkie <duncannwilkie@gmail.com>