module Factory.Math.Pi(
Algorithmic(..),
Category(..)
) where
import qualified Factory.Math.Precision as Math.Precision
import qualified ToolShed.Defaultable
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 (
ToolShed.Defaultable.Defaultable agm,
ToolShed.Defaultable.Defaultable bbp,
ToolShed.Defaultable.Defaultable borwein,
ToolShed.Defaultable.Defaultable ramanujan,
ToolShed.Defaultable.Defaultable spigot
) => ToolShed.Defaultable.Defaultable (Category agm bbp borwein ramanujan spigot) where
defaultValue = BBP ToolShed.Defaultable.defaultValue
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