• Harnessing the power of dc.

    From albert@[email protected] to comp.lang.forth on Sun Nov 2 20:32:13 2025
    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