packages feed

remote-0.1: examples/pi/PiCommon.hs

module PiCommon where

import Data.List
import Data.Array

type Number = Double

data Seq = Seq {k::Int, x::Number, base::Int, q::Array Int Number, tobreak::Bool}

haltonSeq :: Int -> Int -> [Number]
haltonSeq offset thebase = let
                    digits = 64::Int
                    seqSetup :: Seq -> Int -> Number -> (Seq, Number)
                    seqSetup s j _ = 
                                     let dj =  (k s `mod` base s)
                                         news = s {k = (k s - dj) `div` fromIntegral (base s), x = x s + (fromIntegral dj * ((q s) ! (j+1)))}     
                                      in
                                        (news,fromIntegral dj)
                    seqContinue :: Seq -> Int -> Number -> (Seq, Number)
                    seqContinue s j dj = 
                                     if tobreak s
                                        then (s,dj)
                                        else 
                                               let newdj = dj+1
                                                   newx = x s + (q s) ! (j+1)
                                               in
                                               if newdj < fromIntegral (base s)
                                                  then (s {x=newx,tobreak=True},newdj)
                                                  else (s {x = newx - if j==0 then 1 else (q s) ! j},0)

                    initialState base = let q = array (0,digits*2) [(i,v) | i <- [0..digits*2], let v = if i == 0 then 1 else ((q ! ((i)-1))/fromIntegral base)]
                                        in Seq {k=fromIntegral offset,x=0,tobreak=False,base=base,q=q}
                    theseq base = let
                        first :: (Int,[Number],Seq)
                        first = foldl' (\(n,li,s) _ -> let (news,r) = seqSetup s n 0
                                                       in (n+1,r:li,news)) (0,[],initialState base) [0..digits]
                        second :: [Number] -> Seq -> (Int,[Number],Seq)
                        second d s = foldl' (\(n,li,s) dj -> let (news,r) = seqContinue s n dj
                                                             in (n+1,r:li,news)) (0,[],s {tobreak=False}) d
                        in let (_,firstd,firsts) = first
                               therest1 :: [([Number],Seq)]
                               therest1 = iterate (\(d,s) -> let (_,newd,news) = second (reverse d) s in (newd,news)) (firstd,firsts)
                               therest :: [Number]
                               therest = map (\(_,s) -> x s) therest1
                           in therest
                        in (theseq thebase)

haltonPairs :: Int -> [(Number,Number)]
haltonPairs offset = 
  zip (haltonSeq offset 2) (haltonSeq offset 3)

countPairs :: Int -> Int -> (Int,Int)
countPairs offset count = 
  let range = take count (haltonPairs offset)
      numout = length (filter outCircle range)
   in (count-numout,numout)
  where
     outCircle (x,y) = 
          let fx=x-0.5 
              fy=y-0.5
           in fx*fx + fy*fy > 0.25

longdiv :: Integer -> Integer -> Integer -> String
longdiv _ 0 _ = "<inf>"
longdiv numer denom places = 
  let attempt = numer `div` denom 
   in if places==0
         then "" 
         else shows attempt (longdiv2 (numer - attempt*denom) denom (places -1))
   where longdiv2 numer denom places | numer `rem` denom == 0 = "0"
                                     | otherwise = longdiv (numer * 10) denom places