module Factory.Math.Pi(
Algorithmic(..),
Category(..)
) where
import qualified Data.Default
import qualified Factory.Math.Precision as Math.Precision
class Algorithmic algorithm where
openR :: algorithm -> Math.Precision.DecimalDigits -> Rational
openI :: algorithm -> Math.Precision.DecimalDigits -> Integer
openI _ 1 = 3
openI algorithm decimalDigits
| decimalDigits <= 0 = error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits
| otherwise = round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits
openS :: algorithm -> Math.Precision.DecimalDigits -> String
openS _ 1 = "3"
openS algorithm decimalDigits
| decimalDigits <= 0 = ""
| decimalDigits <= 16 = take (succ decimalDigits) $ show (pi :: Double)
| otherwise = "3." ++ tail (show $ openI algorithm decimalDigits)
data Category agm bbp borwein ramanujan spigot
= AGM agm
| BBP bbp
| Borwein borwein
| Ramanujan ramanujan
| Spigot spigot
deriving (Eq, Read, Show)
instance Data.Default.Default bbp => Data.Default.Default (Category agm bbp borwein ramanujan spigot) where
def = BBP Data.Default.def
instance (
Algorithmic agm,
Algorithmic bbp,
Algorithmic borwein,
Algorithmic ramanujan,
Algorithmic spigot
) => Algorithmic (Category agm bbp borwein ramanujan spigot) where
openR algorithm decimalDigits
| decimalDigits <= 0 = error $ "Factory.Math.Pi.openR:\tinsufficient decimalDigits=" ++ show decimalDigits
| decimalDigits <= 16 = Math.Precision.simplify (pred decimalDigits) (pi :: Double)
| otherwise = (
case algorithm of
AGM agm -> openR agm
BBP bbp -> openR bbp
Borwein borwein -> openR borwein
Ramanujan ramanujan -> openR ramanujan
Spigot spigot -> openR spigot
) decimalDigits
openI _ 1 = 3
openI (Spigot spigot) decimalDigits = openI spigot decimalDigits
openI algorithm decimalDigits
| decimalDigits <= 0 = error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits
| otherwise = round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits