Task: Pi




Go: package main

import (
    "fmt"
    "math/big"
)

type lft struct {
    q,r,s,t big.Int
}

func (t *lft) extr(x *big.Int) *big.Rat {
    var n, d big.Int
    var r big.Rat
    return r.SetFrac(
        n.Add(n.Mul(&t.q, x), &t.r),
        d.Add(d.Mul(&t.s, x), &t.t))
}

var three = big.NewInt(3)
var four = big.NewInt(4)

func (t *lft) next() *big.Int {
    r := t.extr(three)
    var f big.Int
    return f.Div(r.Num(), r.Denom())
}

func (t *lft) safe(n *big.Int) bool {
    r := t.extr(four)
    var f big.Int
    if n.Cmp(f.Div(r.Num(), r.Denom())) == 0 {
        return true
    }
    return false
}

func (t *lft) comp(u *lft) *lft {
    var r lft
    var a, b big.Int
    r.q.Add(a.Mul(&t.q, &u.q), b.Mul(&t.r, &u.s))
    r.r.Add(a.Mul(&t.q, &u.r), b.Mul(&t.r, &u.t))
    r.s.Add(a.Mul(&t.s, &u.q), b.Mul(&t.t, &u.s))
    r.t.Add(a.Mul(&t.s, &u.r), b.Mul(&t.t, &u.t))
    return &r
}

func (t *lft) prod(n *big.Int) *lft {
    var r lft
    r.q.SetInt64(10)
    r.r.Mul(r.r.SetInt64(-10), n)
    r.t.SetInt64(1)
    return r.comp(t)
}

func main() {
    
    z := new(lft)
    z.q.SetInt64(1)
    z.t.SetInt64(1)

    
    var k int64
    lfts := func() *lft {
        k++
        r := new(lft)
        r.q.SetInt64(k)
        r.r.SetInt64(4*k+2)
        r.t.SetInt64(2*k+1)
        return r
    }

    
    for {
        y := z.next()
        if z.safe(y) {
            fmt.Print(y)
            z = z.prod(y)
        } else {
            z = z.comp(lfts())
        }
    }
}








Ada: with Ada.Command_Line;
with Ada.Text_IO;
with GNU_Multiple_Precision.Big_Integers;
with GNU_Multiple_Precision.Big_Rationals;
use GNU_Multiple_Precision;

procedure Pi_Digits is
   type Int is mod 2 ** 64;
   package Int_To_Big is new Big_Integers.Modular_Conversions (Int);

   
   Zero : constant Big_Integer := Int_To_Big.To_Big_Integer (0);
   One : constant Big_Integer := Int_To_Big.To_Big_Integer (1);
   Two : constant Big_Integer := Int_To_Big.To_Big_Integer (2);
   Three : constant Big_Integer := Int_To_Big.To_Big_Integer (3);
   Four : constant Big_Integer := Int_To_Big.To_Big_Integer (4);
   Ten : constant Big_Integer := Int_To_Big.To_Big_Integer (10);

   
   type LFT is record
      Q, R, S, T : Big_Integer;
   end record;

   
   function Extr (T : LFT; X : Big_Integer) return Big_Rational is
      use Big_Integers;
      Result : Big_Rational;
   begin
      
      
      Big_Rationals.Set_Numerator (Item         => Result,
                                   New_Value    => T.Q * X + T.R,
                                   Canonicalize => False);
      Big_Rationals.Set_Denominator (Item      => Result,
                                     New_Value => T.S * X + T.T);
      return Result;
   end Extr;

   
   function Unit return LFT is
   begin
      
      return LFT'(Q => One, R => Zero, S => Zero, T => One);
   end Unit;

   
   function Comp (T1, T2 : LFT) return LFT is
      use Big_Integers;
   begin
      
      return LFT'(Q => T1.Q * T2.Q + T1.R * T2.S,
                  R => T1.Q * T2.R + T1.R * T2.T,
                  S => T1.S * T2.Q + T1.T * T2.S,
                  T => T1.S * T2.R + T1.T * T2.T);
   end Comp;

   
   K : Big_Integer := Zero;
   function LFTS return LFT is
      use Big_Integers;
   begin
      K := K + One;
      return LFT'(Q => K,
                  R => Four * K + Two,
                  S => Zero,
                  T => Two * K + One);
   end LFTS;

   
   function Next (T : LFT) return Big_Integer is
   begin
      return Big_Rationals.To_Big_Integer (Extr (T, Three));
   end Next;

   
   function Safe (T : LFT; N : Big_Integer) return Boolean is
   begin
      return N = Big_Rationals.To_Big_Integer (Extr (T, Four));
   end Safe;

   
   function Prod (T : LFT; N : Big_Integer) return LFT is
      use Big_Integers;
   begin
      return Comp (LFT'(Q => Ten, R => -Ten * N, S => Zero, T => One), T);
   end Prod;

   procedure Print_Pi (Digit_Count : Positive) is
      Z : LFT := Unit;
      Y : Big_Integer;
      Count : Natural := 0;
   begin
      loop
         Y := Next (Z);
         if Safe (Z, Y) then
            Count := Count + 1;
            Ada.Text_IO.Put (Big_Integers.Image (Y));
            exit when Count >= Digit_Count;
            Z := Prod (Z, Y);
         else
            Z := Comp (Z, LFTS);
         end if;
      end loop;
   end Print_Pi;

   N : Positive := 250;
begin
   if Ada.Command_Line.Argument_Count = 1 then
      N := Positive'Value (Ada.Command_Line.Argument (1));
   end if;
   Print_Pi (N);
end Pi_Digits;