Pi calculation/display update

Here is an updated version of my original Pi calculation. Instead of using the print area that doesn’t show a very wide display, I’m using the full text area of the screen. Depending on the width of the device, I’ll show 25, 50, 75, 100, 125, or 150 digits across. In the upper right of the screen is the ending digit count for the top row. That makes it easier to find a certain position of Pi. Since I’m using the text area, you can scroll up or down thru the digits. I only scroll the digits that are visible instead of scrolling the full string of digits. That means scrolling 200,000 digits is just as fast as scrolling 5,000 digits. Somewhere above the 200,000 digit calculation is about the max that can be calculated because of math overflow giving wrong calculations. Actually math overflow starts around 185,000 digits, but it isnt bad enough to affect 200,000 digits. I copied 200,000 digits from a Google search and compared each of the digits of the Google list to my list. All 200,000 digits were correct.

-- Codea V3

viewer.mode=STANDARD

function setup()
    textMode(LEFT)
    fill(255)
    s=require("socket")
    parameter.text("digits")
    parameter.action("calc",calc)
    dy=0
end

function draw()
    background(0)
    if str~=nil then
        showText()
    end
end

function calc() 
    output.clear() 
    if digits=="" or string.sub(digits,1,1)==" " then
        alert("digits is blank")
        return
    end
    print("Calculating "..digits.." digits of pi.")
    local pi,tab={},{}
    local size=math.ceil(digits/7)+1
    local size1=math.ceil(size*7)
    local sum,carry,b,z2
    local d1,d2=10000000,9999999 
    local sf=string.format
    local mm=math.modf
    
    start=s.gettime()
    
    for z=0,size1 do
        tab[z]=5*z+3
    end 
    
    for t=1,size do
        carry=0
        for z=size1,0,-1 do
            z2=z*z
            sum=tab[z]*d1+carry
            b=27*(z2+z)+6
            tab[z]=sum%b
            carry=(sum//b)*(2*z2-z)
        end       
        tab[0]=sum%d1
        pi[t]=sum//d1
    end  
    
    carry=0
    for z=size,1,-1 do
        b=pi[z]+carry
        if b>d2 then
            b=b-d1
            carry=1
        else
            carry=0
        end
        pi[z]=sf("%07d",b)
    end 
    
    str=table.concat(pi)
    sec=s.gettime()-start
    val=string.format("%s %0.3f %s",digits.."  digits ",sec," seconds")
    viewer.mode=FULLSCREEN
end

function showText()
    text(val,WIDTH/6,HEIGHT-20)
    st,z,en,y=0,0,0,1
    tab={150,125,100,75,50,25}  -- digits per line based on screen width
    for z=1,#tab do
        if tab[z]<=WIDTH//11 then
            lineWidth=tab[z]
            break
        end
    end
    pageLength=HEIGHT//22*lineWidth   
    st=(dy//20)*lineWidth+8
    en=st+pageLength-1
    for t=st,en do
        z=z+1       
        if t<=digits//1+7 then
            text(string.sub(str,t,t),20+z*10,HEIGHT-20*y-20)            
        end
        if z>=lineWidth then
            z=0
            y=y+1
        end
    end
    
    if st+lineWidth-8>=digits//1 then
        text(string.format("%6d",digits),WIDTH-80,HEIGHT-20)
    else
        text(string.format("%6d",st+lineWidth-8),WIDTH-80,HEIGHT-20)
    end
    if st+lineWidth-8<=lineWidth then
        text("3.",30,HEIGHT-20)
    end
end

function touched(t)
    if t.state==CHANGED then
        dy=dy+t.deltaY
        if dy<0 then
            dy=0
        end
    end
end
1 Like

I love the custom scrolling you have to view the digits when off screen, such a small amount of code to implement a fairly complicated behaviour