module Math.QuadEq where
import Control.Monad
import Math.Utils
solveQuadEq :: Integer -> Integer -> Integer -> [Double]
solveQuadEq :: Integer -> Integer -> Integer -> [Double]
solveQuadEq Integer
a Integer
b Integer
c
| Integer
a Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = [Char] -> [Double]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [Double]) -> [Char] -> [Double]
forall a b. (a -> b) -> a -> b
$ [Char]
"solveQuadEq: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> (Integer, Integer, Integer) -> [Char]
forall a. Show a => a -> [Char]
show (Integer
a, Integer
b, Integer
c)
| Integer
d Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = []
| Integer
d Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = [-Double
b' Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
a')]
| Integer
b Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0
, Double
x0 <- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c' Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (-Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
sqrt Double
d')
, Double
x1 <- (-Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
sqrt Double
d') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
a') =
if Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0 then [Double
x0, Double
x1] else [Double
x1, Double
x0]
| Double
x0 <- (-Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
sqrt Double
d') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
a')
, Double
x1 <- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c' Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (-Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
sqrt Double
d') =
if Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0 then [Double
x0, Double
x1] else [Double
x1, Double
x0]
where
d :: Integer
d = Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
4 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
c
a' :: Double
a' = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
a
b' :: Double
b' = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
b
c' :: Double
c' = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
c
d' :: Double
d' = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
d
solveQuadEqInteger :: Integer -> Integer -> Integer -> [Integer]
solveQuadEqInteger :: Integer -> Integer -> Integer -> [Integer]
solveQuadEqInteger Integer
a Integer
b Integer
c
| Integer
a Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = [Char] -> [Integer]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [Integer]) -> [Char] -> [Integer]
forall a b. (a -> b) -> a -> b
$ [Char]
"solveQuadEqInteger: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> (Integer, Integer, Integer) -> [Char]
forall a. Show a => a -> [Char]
show (Integer
a, Integer
b, Integer
c)
| Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = Integer -> Integer -> Integer -> [Integer]
solveQuadEqInteger (-Integer
a) (-Integer
b) (-Integer
c)
solveQuadEqInteger Integer
a Integer
b Integer
c
| Integer
d Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = []
| Integer
d Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0, (Integer
x, Integer
0) <- Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
quotRem (-Integer
b) (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a) = [Integer
x]
| Bool
otherwise = do
let !sqrtD :: Integer
sqrtD = Integer -> Integer
integerFloorSqrt Integer
d
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> [()]) -> Bool -> [()]
forall a b. (a -> b) -> a -> b
$ Integer
sqrtD Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
sqrtD Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
d
(!x, 0) <- (Integer -> (Integer, Integer))
-> [Integer] -> [(Integer, Integer)]
forall a b. (a -> b) -> [a] -> [b]
map (Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
`quotRem` (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a)) [-Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
sqrtD, -Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
sqrtD]
pure x
where
!d :: Integer
d = Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
4 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
c