Harnessing the power of dc.
From Newsgroup: comp.lang.forth
I connected my Forth to the calculator dc with double pipes,
such that I can do "infinite" precision arithmetic.
The advantage is not more convenience for the arithmetic per se,
by it can be combined with Forth stuff.
A rare case of conditional compilation, to make it work on
64-bits processors. L@ is a 32 bit fetch. The unix boys insisted
that they couldn't use normal 64-bit integers for the pipe
channel numbers.
\ --------------------------------------------------------------
\ Copyright (2012): Albert van der Horst {by GNU Public License}
\ An interface with the program dc that can handle h-numbers (huge).
WANT class
WANT -syscalls-
WANT FORMAT
WANT [IF]
WANT SLITERAL
1,000,000 CONSTANT SIZE
CREATE outputbuffer 0 , SIZE ALLOT
CREATE inputbuffer SIZE ALLOT \ dev directory, can be large.
\ Reorganise for 64 bits, noop for 32 bits.
1 CELLS 8 = [IF]
: convert >R
R@ 4 + L@ R@ CELL+ !
R@ L@ R@ !
R> ;
[ELSE]
: convert ;
[THEN]
class PIPE
M: init-pipe DUP _ _ __NR_pipe XOS THROW
convert DROP M;
M: linkp-in @ M;
M: pipe> @ READ-FILE THROW M; _ ,
M: linkp-out @ M;
M: >pipe @ WRITE-FILE THROW M; _ ,
endclass
\ Make dx execute any hanging commands.
: flush-dc outputbuffer >R ^J R@ $C+ R@ $@ >pipe 0 R> ! ;
: >pipe outputbuffer $+! ;
\ Send one CHARACTER c.
: ch>pipe DSP@ 1 >pipe DROP ;
PIPE fromextern \ Pipe get data from to external programs.
PIPE toextern \ Pipe to talk to external programs.
: start-dc
fromextern init-pipe toextern init-pipe
fromextern linkp-out
toextern linkp-in
"dc <&%d >&%d &" FORMAT
\ "tee dc.txt | dc <&%d >&%d &" FORMAT
SYSTEM ;
\ Send single letter command to dc.
: cmd1 toextern ch>pipe ;
: stop-dc &q cmd1 flush-dc ;
\ Send STRING command to dc.
: command toextern >pipe BL cmd1 ;
\ Get output STRING back from dc.
: get fromextern inputbuffer DUP SIZE pipe> ;
: $>S command ;
: >S "%d " FORMAT command ;
: S>$ "ps_" command flush-dc get ;
: S> S>$ EVALUATE ;
: +' &+ cmd1 ;
: -' &- cmd1 ;
: *' &* cmd1 ;
: /' &/ cmd1 ;
: MOD' &% cmd1 ;
: /MOD' &~ cmd1 &r cmd1 ;
: **' &^ cmd1 ;
: */' "s_ * l_ /" command ;
: x^x' &| cmd1 ;
\ Huge numbers are preceeded by h . Note they are only strings in Forth!
'ONLY >WID CURRENT !
: h NAME STATE @ IF POSTPONE SLITERAL POSTPONE command ELSE command THEN ; IMMEDIATE PREFIX \ In the minimum ONLY search order, no conflicts. DEFINITIONS
: DROP' "s_" command ;
: SWAP' &r cmd1 ;
: DUP' &d cmd1 ;
\ ----------------------------------------------------------
Huge numbers have the prefix h
Operators have the suffix '.
Examples:
h100 h10000 **' S>$ .S
[S[ 5274704 20580 ] OK
\ This is a 1 followed by some zeroes, I will not print this).
Example tests :
REGRESS h13 h3 +' S> S: 16
REGRESS h13 h3 /MOD' S> S> S: 4 1
REGRESS h13 h2 h70 x^x' S> S: 29 \ Modular exponentiation.
REGRESS h1 h2 h3 h4 SWAP' S> S> S> S> S: 3 4 2 1
In practice you would never use S> because normally huge number
strings cannot be evaluated by Forth.
Groetjes Albert
--
The Chinese government is satisfied with its military superiority over USA.
The next 5 year plan has as primary goal to advance life expectancy
over 80 years, like Western Europe.
--- Synchronet 3.21a-Linux NewsLink 1.2