{-
Copyright (C) 2011 Dr. Alistair Ward
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@]
* Implements a /Bailey-Borwein-Plouffe/ formula;
* Surprisingly, because of the huge size of the 'Rational' quantities,
it is a /single/ call to @Factory.Math.Summation.sum'@, rather than the calculation of the many terms in the series, which is the performance-bottleneck.
-}
module Factory.Math.Implementations.Pi.BBP.Implementation(
-- * Functions
openR
) where
import Data.Ratio((%))
import qualified Factory.Math.Implementations.Pi.BBP.Series as Math.Implementations.Pi.BBP.Series
import qualified Factory.Math.Precision as Math.Precision
import qualified Factory.Math.Summation as Math.Summation
-- | Returns /Pi/, accurate to the specified number of decimal digits.
openR
:: Math.Implementations.Pi.BBP.Series.Series -- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.
-> Math.Precision.DecimalDigits -- ^ The number of decimal digits required.
-> Rational
openR Math.Implementations.Pi.BBP.Series.MkSeries {
Math.Implementations.Pi.BBP.Series.numerators = numerators,
Math.Implementations.Pi.BBP.Series.getDenominators = getDenominators,
Math.Implementations.Pi.BBP.Series.seriesScalingFactor = seriesScalingFactor,
Math.Implementations.Pi.BBP.Series.base = base
} decimalDigits = (seriesScalingFactor *) . Math.Summation.sum' 8 . take (
Math.Precision.getTermsRequired (
recip . fromIntegral $ abs {-potentially negative-} base -- The convergence-rate.
) decimalDigits
) . zipWith (*) (
iterate (/ fromIntegral base) 1 -- Generate the scaling-ratio, between successive terms.
) $ map (
sum . zipWith (%) numerators . getDenominators
) [0 ..]