module Factory.Math.SquareRoot(
Algorithmic(..),
Iterator(..),
Result,
Estimate,
getAccuracy,
getDiscrepancy,
getEstimate,
isPrecise
) where
import qualified Factory.Math.Power as Math.Power
import qualified Factory.Math.Precision as Math.Precision
type Result = Rational
type Estimate = (Result, Math.Precision.DecimalDigits)
class Algorithmic algorithm where
squareRootFrom :: (Real operand, Show operand)
=> algorithm
-> Estimate
-> Math.Precision.DecimalDigits
-> operand
-> Result
squareRoot :: (Real operand, Show operand)
=> algorithm
-> Math.Precision.DecimalDigits
-> operand
-> Result
squareRoot algorithm
algorithm DecimalDigits
decimalDigits operand
operand = algorithm -> Estimate -> DecimalDigits -> operand -> Result
forall algorithm operand.
(Algorithmic algorithm, Real operand, Show operand) =>
algorithm -> Estimate -> DecimalDigits -> operand -> Result
squareRootFrom algorithm
algorithm (operand -> Estimate
forall operand. (Real operand, Show operand) => operand -> Estimate
getEstimate operand
operand) DecimalDigits
decimalDigits operand
operand
class Iterator algorithm where
step :: Real operand
=> algorithm
-> operand
-> Result
-> Result
convergenceOrder :: algorithm -> Math.Precision.ConvergenceOrder
rSqrt :: Real operand => operand -> Double
rSqrt :: operand -> Double
rSqrt = Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Double) -> (operand -> Double) -> operand -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. operand -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac
getEstimate :: (Real operand, Show operand) => operand -> Estimate
getEstimate :: operand -> Estimate
getEstimate operand
y
| operand
y operand -> operand -> Bool
forall a. Ord a => a -> a -> Bool
< operand
0 = [Char] -> Estimate
forall a. HasCallStack => [Char] -> a
error ([Char] -> Estimate) -> [Char] -> Estimate
forall a b. (a -> b) -> a -> b
$ [Char]
"Factory.Math.SquareRoot.getEstimate:\tthere's no real square-root of " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ operand -> [Char]
forall a. Show a => a -> [Char]
show operand
y
| Bool
otherwise = (DecimalDigits -> Result -> Result
forall operand.
RealFrac operand =>
DecimalDigits -> operand -> Result
Math.Precision.simplify DecimalDigits
decimalDigits (Result -> Result) -> (Double -> Result) -> Double -> Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Result
forall a. Real a => a -> Result
toRational (Double -> Result) -> Double -> Result
forall a b. (a -> b) -> a -> b
$ operand -> Double
forall operand. Real operand => operand -> Double
rSqrt operand
y, DecimalDigits
decimalDigits)
where
decimalDigits :: Math.Precision.DecimalDigits
decimalDigits :: DecimalDigits
decimalDigits = DecimalDigits
16
getDiscrepancy :: Real operand => operand -> Result -> Result
getDiscrepancy :: operand -> Result -> Result
getDiscrepancy operand
y Result
x = operand -> Result
forall a. Real a => a -> Result
toRational operand
y Result -> Result -> Result
forall a. Num a => a -> a -> a
- Result -> Result
forall n. Num n => n -> n
Math.Power.square Result
x
isPrecise :: Real operand => operand -> Result -> Bool
isPrecise :: operand -> Result -> Bool
isPrecise operand
y Result
x = operand -> Result -> Result
forall operand. Real operand => operand -> Result -> Result
getDiscrepancy operand
y Result
x Result -> Result -> Bool
forall a. Eq a => a -> a -> Bool
== Result
0
getAccuracy :: Real operand => operand -> Result -> Math.Precision.DecimalDigits
getAccuracy :: operand -> Result -> DecimalDigits
getAccuracy operand
y Result
x
| Result
absoluteError Result -> Result -> Bool
forall a. Eq a => a -> a -> Bool
== Result
0 = DecimalDigits
forall a. Bounded a => a
maxBound
| Bool
otherwise = [Char] -> DecimalDigits
forall (t :: * -> *) a. Foldable t => t a -> DecimalDigits
length ([Char] -> DecimalDigits) -> [Char] -> DecimalDigits
forall a b. (a -> b) -> a -> b
$ Integer -> [Char]
forall a. Show a => a -> [Char]
show (Result -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Result -> Integer) -> Result -> Integer
forall a b. (a -> b) -> a -> b
$ operand -> Result
forall a. Real a => a -> Result
toRational operand
y Result -> Result -> Result
forall a. Fractional a => a -> a -> a
/ Result
absoluteError :: Integer)
where
absoluteError :: Result
absoluteError :: Result
absoluteError = Result -> Result
forall n. Num n => n -> n
abs (operand -> Result -> Result
forall operand. Real operand => operand -> Result -> Result
getDiscrepancy operand
y Result
x) Result -> Result -> Result
forall a. Fractional a => a -> a -> a
/ Result
2