
Create a program to continually calculate and output the next decimal digit of   



π


{\displaystyle \pi }

   (pi).

The program should continue forever (until it is aborted by the user) calculating and outputting each decimal digit in succession.

The output should be a decimal sequence beginning   3.14159265 ...



Note: this task is about   calculating   pi.   For information on built-in pi constants see Real constants and functions.



Related Task Arithmetic-geometric mean/Calculate Pi

CLASS BIGNUM;
BEGIN
 
    BOOLEAN PROCEDURE TISZERO(T); TEXT T;
        TISZERO := T = "0";
 
    TEXT PROCEDURE TSHL(T); TEXT T;
        TSHL :- IF TISZERO(T) THEN T ELSE T & "0";
 
    TEXT PROCEDURE TSHR(T); TEXT T;
        TSHR :- IF T.LENGTH = 1 THEN "0" ELSE T.SUB(1, T.LENGTH - 1);
 
    INTEGER PROCEDURE TSIGN(T); TEXT T;
        TSIGN := IF TISZERO(T) THEN 0
            ELSE IF T.SUB(1, 1) = "-" THEN -1
            ELSE 1;
 
    TEXT PROCEDURE TABS(T); TEXT T;
        TABS :- IF TSIGN(T) < 0 THEN T.SUB(2, T.LENGTH - 1) ELSE T;
 
    TEXT PROCEDURE TNEGATE(T); TEXT T;
        TNEGATE :- IF TSIGN(T) <= 0 THEN TABS(T) ELSE ("-" & T);
 
    TEXT PROCEDURE TREVERSE(T); TEXT T;
    BEGIN
        INTEGER I, J;
        I := 1; J := T.LENGTH;
        WHILE I < J DO
        BEGIN CHARACTER C1, C2;
            T.SETPOS(I); C1 := T.GETCHAR;
            T.SETPOS(J); C2 := T.GETCHAR;
            T.SETPOS(I); T.PUTCHAR(C2);
            T.SETPOS(J); T.PUTCHAR(C1);
            I := I + 1;
            J := J - 1;
        END;
        TREVERSE :- T;
    END TREVERSE;
 
    INTEGER PROCEDURE TCMPUNSIGNED(A, B); TEXT A, B;
    BEGIN
        INTEGER ALEN, BLEN, RESULT;
        ALEN := A.LENGTH; BLEN := B.LENGTH;
        IF ALEN < BLEN THEN
            RESULT := -1
        ELSE IF ALEN > BLEN THEN
            RESULT := 1
        ELSE BEGIN
            INTEGER CMP, I; BOOLEAN DONE;
            A.SETPOS(1);
            B.SETPOS(1);
            I := 1;
            WHILE I <= ALEN AND NOT DONE DO
            BEGIN
                I := I + 1;
                CMP := RANK(A.GETCHAR) - RANK(B.GETCHAR);
                IF NOT (CMP = 0) THEN
                    DONE := TRUE;
            END;
            RESULT := CMP;
        END;
        TCMPUNSIGNED := RESULT;
    END TCMPUNSIGNED;
 
    INTEGER PROCEDURE TCMP(A, B); TEXT A, B;
    BEGIN
        BOOLEAN ANEG, BNEG;
        ANEG := TSIGN(A) < 0; BNEG := TSIGN(B) < 0;
        IF ANEG AND BNEG THEN
           TCMP := -TCMPUNSIGNED(TABS(A), TABS(B))
        ELSE IF NOT ANEG AND BNEG THEN
           TCMP := 1
        ELSE IF ANEG AND NOT BNEG THEN
           TCMP := -1
        ELSE
           TCMP := TCMPUNSIGNED(A, B);
    END TCMP;
 
    TEXT PROCEDURE TADDUNSIGNED(A, B); TEXT A, B;
    BEGIN
        INTEGER CARRY, I, J;
        TEXT BF;
        I := A.LENGTH;
        J := B.LENGTH;
        BF :- BLANKS(MAX(I, J) + 1);
        WHILE I >= 1 OR J >= 1 DO BEGIN
            INTEGER X, Y, Z;
            IF I >= 1 THEN BEGIN
                A.SETPOS(I); I := I - 1; X := RANK(A.GETCHAR) - RANK('0');
            END;
            IF J >= 1 THEN BEGIN
                B.SETPOS(J); J := J - 1; Y := RANK(B.GETCHAR) - RANK('0');
            END;
            Z := X + Y + CARRY;
            IF Z < 10 THEN
            BEGIN BF.PUTCHAR(CHAR(Z + RANK('0'))); CARRY := 0;
            END ELSE
            BEGIN BF.PUTCHAR(CHAR(MOD(Z, 10) + RANK('0'))); CARRY := 1;
            END;
        END;
        IF CARRY > 0 THEN
            BF.PUTCHAR(CHAR(CARRY + RANK('0')));
        BF :- TREVERSE(BF.STRIP);
        TADDUNSIGNED :- BF;
    END TADDUNSIGNED;
 
    TEXT PROCEDURE TADD(A, B); TEXT A, B;
    BEGIN
        BOOLEAN ANEG, BNEG;
        ANEG := TSIGN(A) < 0; BNEG := TSIGN(B) < 0;
        IF NOT ANEG AND BNEG THEN          ! (+7)+(-5) =  (7-5) =   2 ;
            TADD :- TSUBUNSIGNED(A, TABS(B))
        ELSE IF ANEG AND NOT BNEG THEN     ! (-7)+(+5) =  (5-7) =  -2 ;
            TADD :- TSUBUNSIGNED(B, TABS(A))
        ELSE IF ANEG AND BNEG THEN         ! (-7)+(-5) = -(7+5) = -12 ;
            TADD :- TNEGATE(TADDUNSIGNED(TABS(A), TABS(B)))
        ELSE                               ! (+7)+(+5) =  (7+5) =  12 ;
            TADD :- TADDUNSIGNED(A, B);
    END TADD;
 
    TEXT PROCEDURE TSUBUNSIGNED(A, B); TEXT A, B;
    BEGIN
        INTEGER I, J, CARRY;
        I := A.LENGTH; J := B.LENGTH;
        IF I < J OR I = J AND A < B THEN
            TSUBUNSIGNED :- TNEGATE(TSUBUNSIGNED(B, A)) ELSE
        BEGIN
            TEXT BF;
            BF :- BLANKS(MAX(I, J) + 1);
            WHILE I >= 1 OR J >= 1 DO
            BEGIN
                INTEGER X, Y, Z;
                IF I >= 1 THEN
                BEGIN A.SETPOS(I); I := I - 1;
                    X := RANK(A.GETCHAR) - RANK('0');
                END;
                IF J >= 1 THEN
                BEGIN B.SETPOS(J); J := J - 1;
                    Y := RANK(B.GETCHAR) - RANK('0');
                END;
                Z := X - Y - CARRY;
                IF Z >= 0 THEN
                BEGIN
                    BF.PUTCHAR(CHAR(RANK('0') + Z));
                    CARRY := 0;
                END ELSE
                BEGIN
                    BF.PUTCHAR(CHAR(RANK('0') + MOD(10 + Z, 10)));
                    CARRY := 1; ! (Z / 10);
                END;
            END;
            BF :- BF.STRIP;
            BF :- TREVERSE(BF);
            BF.SETPOS(1);
            WHILE BF.LENGTH > 1 AND THEN BF.GETCHAR = '0' DO
            BEGIN
                BF :- BF.SUB(2, BF.LENGTH - 1);
                BF.SETPOS(1);
            END;
            TSUBUNSIGNED :- BF;
        END;
    END TSUBUNSIGNED;
 
    TEXT PROCEDURE TSUB(A, B); TEXT A, B;
    BEGIN
        BOOLEAN ANEG, BNEG;
        ANEG := TSIGN(A) < 0; BNEG := TSIGN(B) < 0;
        IF ANEG AND BNEG THEN              ! (-7)-(-5) = -(7-5) =  -2 ;
            TSUB :- TNEGATE(TSUBUNSIGNED(TABS(A), TABS(B)))
        ELSE IF NOT ANEG AND BNEG THEN     ! (+7)-(-5) =  (7+5) =  12 ;
            TSUB :- TADDUNSIGNED(A, TABS(B))
        ELSE IF ANEG AND NOT BNEG THEN     ! (-7)-(+5) = -(7+5) = -12 ;
            TSUB :- TNEGATE(TADDUNSIGNED(TABS(A), B))
        ELSE                               ! (+7)-(+5) =  (7-5) =   2 ;
            TSUB :- TSUBUNSIGNED(A, B);
    END TSUB;
 
    TEXT PROCEDURE TMULUNSIGNED(A, B); TEXT A, B;
    BEGIN
        INTEGER ALEN, BLEN;
        ALEN := A.LENGTH; BLEN := B.LENGTH;
        IF ALEN < BLEN THEN
            TMULUNSIGNED :- TMULUNSIGNED(B, A)
        ELSE BEGIN
            TEXT PRODUCT; INTEGER J;
            PRODUCT :- "0";
            FOR J := 1 STEP 1 UNTIL BLEN DO BEGIN
                TEXT PART; INTEGER I, Y, CARRY;
                B.SETPOS(J); Y := RANK(B.GETCHAR) - RANK('0');
                PART :- BLANKS(ALEN + BLEN + 1); PART.SETPOS(1);
                FOR I := ALEN STEP -1 UNTIL 1 DO BEGIN
                    INTEGER X, Z;
                    A.SETPOS(I); X := RANK(A.GETCHAR) - RANK('0');
                    Z := X * Y + CARRY;
                    IF Z < 10 THEN BEGIN
                        PART.PUTCHAR(CHAR(RANK('0') + Z));
                        CARRY := 0;
                    END ELSE BEGIN
                        PART.PUTCHAR(CHAR(RANK('0') + MOD(Z, 10)));
                        CARRY := Z // 10;
                    END;
                END;
                IF CARRY > 0 THEN
                    PART.PUTCHAR(CHAR(RANK('0') + CARRY));
                PART :- PART.SUB(1, PART.POS - 1);
                PART :- TREVERSE(PART);
                PART.SETPOS(1);
                WHILE PART.LENGTH > 1 AND THEN PART.GETCHAR = '0' DO
                BEGIN
                    PART :- PART.SUB(2, PART.LENGTH - 1);
                    PART.SETPOS(1);
                END;
                PRODUCT :- TADDUNSIGNED(TSHL(PRODUCT), PART);
            END;
            TMULUNSIGNED :- PRODUCT;
        END;
    END TMULUNSIGNED;
 
    TEXT PROCEDURE TMUL(A, B); TEXT A, B;
    BEGIN
        BOOLEAN ANEG, BNEG;
        ANEG := TSIGN(A) < 0; BNEG := TSIGN(B) < 0;
        IF ANEG AND BNEG THEN              ! (-7)*(-5) =  (7*5) =>  35 ;
           TMUL :- TMULUNSIGNED(TABS(A), TABS(B))
        ELSE IF NOT ANEG AND BNEG THEN     ! (+7)*(-5) = -(7*5) => -35 ;
           TMUL :- TNEGATE(TMULUNSIGNED(A, TABS(B)))
        ELSE IF ANEG AND NOT BNEG THEN     ! (-7)*(+5) = -(7*5) => -35 ;
           TMUL :- TNEGATE(TMULUNSIGNED(TABS(A), B))
        ELSE                               ! (+7)*(+5) =  (7*5) =>  35 ;
           TMUL :- TMULUNSIGNED(A, B);
    END TMUL;
 
    CLASS DIVMOD(DIV,MOD); TEXT DIV,MOD;;
 
    REF(DIVMOD) PROCEDURE TDIVMODUNSIGNED(A, B); TEXT A, B;
    BEGIN
        INTEGER CC;
        REF(DIVMOD) RESULT;
        IF TISZERO(B) THEN
            ERROR("DIVISION BY ZERO");
        CC := TCMPUNSIGNED(A, B);
        IF CC < 0 THEN
            RESULT :- NEW DIVMOD("0", A)
        ELSE IF CC = 0 THEN
            RESULT :- NEW DIVMOD("1", "0")
        ELSE BEGIN
            INTEGER ALEN, BLEN, AIDX;
            TEXT Q, R;
            ALEN := A.LENGTH; BLEN := B.LENGTH;
            Q :- BLANKS(ALEN); Q.SETPOS(1);
            R :- BLANKS(ALEN); R.SETPOS(1);
            R := A.SUB(1, BLEN - 1); R.SETPOS(BLEN);
            FOR AIDX := BLEN STEP 1 UNTIL ALEN DO
            BEGIN
                INTEGER COUNT; BOOLEAN DONE;
                IF TISZERO(R.STRIP) THEN
                    R.SETPOS(1);
                A.SETPOS(AIDX); R.PUTCHAR(A.GETCHAR);
                WHILE NOT DONE DO
                BEGIN
                    TEXT DIFF;
                    DIFF :- TSUBUNSIGNED(R.STRIP, B);
                    IF TSIGN(DIFF) < 0 THEN
                        DONE := TRUE
                    ELSE BEGIN
                        R := DIFF; R.SETPOS(DIFF.LENGTH + 1);
                        COUNT := COUNT + 1;
                    END;
                END;
                IF (NOT (COUNT = 0)) OR (NOT (Q.POS = 1)) THEN
                    Q.PUTCHAR(CHAR(COUNT + RANK('0')));
            END;
            RESULT :- NEW DIVMOD(Q.STRIP, R.STRIP);
        END;
        TDIVMODUNSIGNED :- RESULT;
    END TDIVMODUNSIGNED;
 
    REF(DIVMOD) PROCEDURE TDIVMOD(A, B); TEXT A, B;
    BEGIN
        BOOLEAN ANEG, BNEG; REF(DIVMOD) RESULT;
        ANEG := TSIGN(A) < 0; BNEG := TSIGN(B) < 0;
        IF ANEG AND BNEG THEN
            BEGIN
                RESULT :- TDIVMOD(TABS(A), TABS(B));
                RESULT.MOD :- TNEGATE(RESULT.MOD);
            END
        ELSE IF NOT ANEG AND BNEG THEN
            BEGIN
                RESULT :- TDIVMOD(A, TABS(B));
                RESULT.DIV :- TNEGATE(RESULT.DIV);
            END
        ELSE IF ANEG AND NOT BNEG THEN
            BEGIN
                RESULT :- TDIVMOD(TABS(A), B);
                RESULT.DIV :- TNEGATE(RESULT.DIV);
                RESULT.MOD :- TNEGATE(RESULT.MOD);
            END
        ELSE
            RESULT :- TDIVMODUNSIGNED(A, B);
        TDIVMOD :- RESULT;
    END TDIVMOD;
 
    TEXT PROCEDURE TDIV(A, B); TEXT A, B;
        TDIV :- TDIVMOD(A, B).DIV;
 
    TEXT PROCEDURE TMOD(A, B); TEXT A, B;
        TMOD :- TDIVMOD(A, B).MOD;
 
END BIGNUM;