{-# LANGUAGE BangPatterns, NoImplicitPrelude #-}
module UnitFractionsDecomposition2 where
import GHC.Base
import GHC.Num ((+),(-),(*),abs,Integer)
import GHC.List (null,last,head,length,filter,sum,cycle,zip)
import Data.List (minimumBy)
import GHC.Real (Integral,round,fromIntegral,(/),truncate,ceiling)
import GHC.Float (sqrt)
import Data.Maybe (isNothing,isJust,fromJust,catMaybes)
import Data.Ord (comparing)
import Data.Tuple (fst,snd)
threeDigitsK :: Double -> Double
threeDigitsK :: Double -> Double
threeDigitsK Double
k = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round (Double
kforall a. Num a => a -> a -> a
*Double
1000)) forall a. Fractional a => a -> a -> a
/ Double
1000.0
{-# INLINE threeDigitsK #-}
type ErrorImpact = Int
absErr2Frac :: Double -> Double -> Double
absErr2Frac :: Double -> Double -> Double
absErr2Frac Double
k Double
y = Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
y forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round (Double
yforall a. Fractional a => a -> a -> a
/(Double
kforall a. Num a => a -> a -> a
*Double
y forall a. Num a => a -> a -> a
- Double
1.0))) forall a. Num a => a -> a -> a
- Double
k
{-# INLINE absErr2Frac #-}
absErrUDecomp3 :: [Double] -> Double -> Double
absErrUDecomp3 :: [Double] -> Double -> Double
absErrUDecomp3 [Double
x,Double
y,Double
u] Double
k = Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
x forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
u forall a. Num a => a -> a -> a
- Double
k
absErrUDecomp3 [Double
x,Double
y] Double
k = Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
x forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) forall a. Num a => a -> a -> a
- Double
k
absErrUDecomp3 [Double
x] Double
k = Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round Double
x) forall a. Num a => a -> a -> a
- Double
k
absErrUDecomp3 [Double]
_ Double
_ = -Double
1.0
{-# INLINE absErrUDecomp3 #-}
elemSolution2 :: (Integral a) => Int -> a -> Double -> Bool
elemSolution2 :: forall a. Integral a => ErrorImpact -> a -> Double -> Bool
elemSolution2 ErrorImpact
n a
y Double
k = ErrorImpact
n forall a. Eq a => a -> a -> Bool
== ErrorImpact
0 Bool -> Bool -> Bool
|| forall a. Ord a => a -> a -> Ordering
compare ErrorImpact
n ErrorImpact
0 forall a. Eq a => a -> a -> Bool
== forall a. Ord a => a -> a -> Ordering
compare (Double -> Double -> Double
absErr2Frac Double
k (forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y)) Double
0
{-# INLINE elemSolution2 #-}
setOfSolutionsGmin :: ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin :: ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin ErrorImpact
n Double
k
| Double -> Bool
isRangeN Double
k =
let j :: Integer
j = forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
k)
p :: Integer
p = forall a b. (RealFrac a, Integral b) => a -> b
truncate (forall a. Ord a => a -> a -> a
min (Double
2.0 forall a. Fractional a => a -> a -> a
/ Double
k) ((forall a. Floating a => a -> a
sqrt (Double
kforall a. Num a => a -> a -> a
*Double
k forall a. Num a => a -> a -> a
+ Double
16) forall a. Num a => a -> a -> a
- Double
k forall a. Num a => a -> a -> a
+ Double
4)forall a. Fractional a => a -> a -> a
/(Double
4forall a. Num a => a -> a -> a
*Double
k)))
j1 :: Double
j1 = forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
j in
if Integer
j forall a. Eq a => a -> a -> Bool
== Integer
p
then if forall a. Integral a => ErrorImpact -> a -> Double -> Bool
elemSolution2 ErrorImpact
n Integer
j Double
k
then (Double
j1,Double
j1forall a. Fractional a => a -> a -> a
/(Double
kforall a. Num a => a -> a -> a
*Double
j1 forall a. Num a => a -> a -> a
- Double
1.0))
else (Double
0, -Double
1.0)
else (\Double
t -> if forall a. Num a => a -> a
abs (Double
t forall a. Num a => a -> a -> a
+ Double
0.0001) forall a. Ord a => a -> a -> Bool
< Double
0.000001
then (Double
0, Double
0)
else (Double
t, Double
tforall a. Fractional a => a -> a -> a
/(Double
kforall a. Num a => a -> a -> a
*Double
t forall a. Num a => a -> a -> a
- Double
1.0))) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a b. (a -> b -> b) -> b -> [a] -> b
foldr (\Double
x Double
y -> if forall a. Integral a => ErrorImpact -> a -> Double -> Bool
elemSolution2 ErrorImpact
n (forall a b. (RealFrac a, Integral b) => a -> b
round Double
x) Double
k Bool -> Bool -> Bool
&& forall a. Num a => a -> a
abs (Double -> Double -> Double
absErr2Frac Double
k Double
x) forall a. Ord a => a -> a -> Bool
< forall a. Num a => a -> a
abs (Double -> Double -> Double
absErr2Frac Double
k Double
y)
then Double
x
else Double
y) (-Double
0.0001) forall a b. (a -> b) -> a -> b
$ [Double
j1..forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
p]
| Bool
otherwise = (Double
0, -Double
1.0)
{-# INLINE setOfSolutionsGmin #-}
suitable2 :: Double -> (Double,Double)
suitable2 :: Double -> (Double, Double)
suitable2 = ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin ErrorImpact
0
{-# INLINE suitable2 #-}
suitable21G :: ErrorImpact -> Double -> Maybe ([Double],Double)
suitable21G :: ErrorImpact -> Double -> Maybe ([Double], Double)
suitable21G ErrorImpact
n Double
k =
if forall a. Num a => a -> a
abs Double
x forall a. Ord a => a -> a -> Bool
< Double
0.000001
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just ([Double
x, Double
y], Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
x forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) forall a. Num a => a -> a -> a
- Double
k)
where !(Double
x,Double
y) = ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin ErrorImpact
n Double
k
{-# INLINE suitable21G #-}
suitable21 :: Double -> Maybe ([Double],Double)
suitable21 :: Double -> Maybe ([Double], Double)
suitable21 = ErrorImpact -> Double -> Maybe ([Double], Double)
suitable21G ErrorImpact
0
{-# INLINE suitable21 #-}
isRangeN :: Double -> Bool
isRangeN :: Double -> Bool
isRangeN Double
k = Double
k forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k forall a. Ord a => a -> a -> Bool
<= Double
0.9
{-# INLINE isRangeN #-}
isRangeNPref :: Double -> Bool
isRangeNPref :: Double -> Bool
isRangeNPref Double
k = Double
k forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k forall a. Ord a => a -> a -> Bool
< (Double
2.0forall a. Fractional a => a -> a -> a
/Double
3.0)
{-# INLINE isRangeNPref #-}
check1FracDecompG :: ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG :: ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG ErrorImpact
n Double
k
| Double
k forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k forall a. Ord a => a -> a -> Bool
<= Double
0.501 =
let c :: Double
c = (Double
1.0forall a. Fractional a => a -> a -> a
/Double
k)
err :: Double
err = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
round Double
c) forall a. Num a => a -> a -> a
- Double
k
in if Double
err forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral ErrorImpact
n forall a. Ord a => a -> a -> Bool
>= Double
0
then let cs :: [Double]
cs = [Double
c] in forall a. a -> Maybe a
Just ([Double]
cs, [Double] -> Double -> Double
absErrUDecomp3 [Double]
cs Double
k)
else forall a. Maybe a
Nothing
| Bool
otherwise = forall a. Maybe a
Nothing
{-# INLINE check1FracDecompG #-}
check3FracDecompPartialG :: ErrorImpact -> Bool -> Double -> Maybe ([Double],Double)
check3FracDecompPartialG :: ErrorImpact -> Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartialG ErrorImpact
n Bool
direction = ErrorImpact
-> Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialPG ErrorImpact
n Bool
direction []
{-# INLINE check3FracDecompPartialG #-}
check3FracDecompPartialPG :: ErrorImpact -> Bool -> [Int] -> Double -> Maybe ([Double],Double)
check3FracDecompPartialPG :: ErrorImpact
-> Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialPG ErrorImpact
n Bool
direction [ErrorImpact]
ns Double
k
| Double
k forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k forall a. Ord a => a -> a -> Bool
<= Double
1 =
let u :: Maybe Double
u = (\[Double]
us -> if forall a. [a] -> Bool
null [Double]
us
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just (if Bool
direction then forall a. [a] -> a
last [Double]
us else forall a. [a] -> a
head [Double]
us)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (\Double
t -> let w :: Double
w = Double
k forall a. Num a => a -> a -> a
- Double
1.0forall a. Fractional a => a -> a -> a
/Double
t in
Double
w forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
w forall a. Ord a => a -> a -> Bool
<= (Double
2.0forall a. Fractional a => a -> a -> a
/Double
3.0)) forall a b. (a -> b) -> a -> b
$ [Double
2.0..Double
10.0] forall a. Monoid a => a -> a -> a
`mappend` forall a b. (a -> b) -> [a] -> [b]
map forall a b. (Integral a, Num b) => a -> b
fromIntegral [ErrorImpact]
ns in
if forall a. Maybe a -> Bool
isNothing Maybe Double
u
then forall a. Maybe a
Nothing
else let u1 :: Double
u1 = forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u in let s2 :: Maybe ([Double], Double)
s2 = Double -> Maybe ([Double], Double)
suitable21 (Double
k forall a. Num a => a -> a -> a
- Double
1.0 forall a. Fractional a => a -> a -> a
/ Double
u1) in
if forall a. Maybe a -> Bool
isNothing Maybe ([Double], Double)
s2
then forall a. Maybe a
Nothing
else let ([Double
a1,Double
b1],Double
_) = forall a. HasCallStack => Maybe a -> a
fromJust Maybe ([Double], Double)
s2 in let err :: Double
err = [Double] -> Double -> Double
absErrUDecomp3 [Double
a1, Double
b1, Double
u1] Double
k in
if Double
err forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral ErrorImpact
n forall a. Ord a => a -> a -> Bool
>= Double
0
then forall a. a -> Maybe a
Just ([Double
u1,Double
a1,Double
b1], [Double] -> Double -> Double
absErrUDecomp3 [Double
a1, Double
b1, Double
u1] Double
k)
else forall a. Maybe a
Nothing
| Bool
otherwise = forall a. Maybe a
Nothing
{-# INLINE check3FracDecompPartialPG #-}
lessErrSimpleDecompPG :: ErrorImpact -> [Int] -> Double -> (Int,Maybe ([Double],Double),Double)
lessErrSimpleDecompPG :: ErrorImpact
-> [ErrorImpact]
-> Double
-> (ErrorImpact, Maybe ([Double], Double), Double)
lessErrSimpleDecompPG ErrorImpact
n [ErrorImpact]
ns Double
k =
(\[([Double], Double)]
ts -> if forall a. [a] -> Bool
null [([Double], Double)]
ts
then (ErrorImpact
0,forall a. Maybe a
Nothing,-Double
1.0)
else let p :: ([Double], Double)
p = forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy (forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (forall a. Num a => a -> a
abs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd)) [([Double], Double)]
ts in (forall a. [a] -> ErrorImpact
length (forall a b. (a, b) -> a
fst ([Double], Double)
p), forall a. a -> Maybe a
Just ([Double], Double)
p, forall a b. (a, b) -> b
snd ([Double], Double)
p)) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ [ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG ErrorImpact
n Double
k,ErrorImpact -> Double -> Maybe ([Double], Double)
suitable21G ErrorImpact
n Double
k, ErrorImpact
-> Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialPG ErrorImpact
n Bool
True [ErrorImpact]
ns Double
k, ErrorImpact
-> Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialPG ErrorImpact
n Bool
False [ErrorImpact]
ns Double
k]
lessErrDenomsPG :: ErrorImpact -> [Int] -> Double -> [Integer]
lessErrDenomsPG :: ErrorImpact -> [ErrorImpact] -> Double -> [Integer]
lessErrDenomsPG ErrorImpact
n [ErrorImpact]
ns =
(\(ErrorImpact
_,Maybe ([Double], Double)
ks,Double
_) -> if forall a. Maybe a -> Bool
isNothing Maybe ([Double], Double)
ks
then []
else forall a b. (a -> b) -> [a] -> [b]
map forall a b. (RealFrac a, Integral b) => a -> b
round forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ Maybe ([Double], Double)
ks) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorImpact
-> [ErrorImpact]
-> Double
-> (ErrorImpact, Maybe ([Double], Double), Double)
lessErrSimpleDecompPG ErrorImpact
n [ErrorImpact]
ns
{-# INLINE lessErrDenomsPG #-}
check1FracDecomp :: Double -> Maybe ([Double], Double)
check1FracDecomp :: Double -> Maybe ([Double], Double)
check1FracDecomp = ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG ErrorImpact
0
{-# INLINE check1FracDecomp #-}
check3FracDecompPartial :: Bool -> Double -> Maybe ([Double],Double)
check3FracDecompPartial :: Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartial = ErrorImpact -> Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartialG ErrorImpact
0
{-# INLINE check3FracDecompPartial #-}
check3FracDecompPartialP :: Bool -> [Int] -> Double -> Maybe ([Double],Double)
check3FracDecompPartialP :: Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialP = ErrorImpact
-> Bool -> [ErrorImpact] -> Double -> Maybe ([Double], Double)
check3FracDecompPartialPG ErrorImpact
0
{-# INLINE check3FracDecompPartialP #-}
lessErrSimpleDecompP :: [Int] -> Double -> (Int,Maybe ([Double],Double),Double)
lessErrSimpleDecompP :: [ErrorImpact]
-> Double -> (ErrorImpact, Maybe ([Double], Double), Double)
lessErrSimpleDecompP = ErrorImpact
-> [ErrorImpact]
-> Double
-> (ErrorImpact, Maybe ([Double], Double), Double)
lessErrSimpleDecompPG ErrorImpact
0
lessErrDenomsP :: [Int] -> Double -> [Integer]
lessErrDenomsP :: [ErrorImpact] -> Double -> [Integer]
lessErrDenomsP = ErrorImpact -> [ErrorImpact] -> Double -> [Integer]
lessErrDenomsPG ErrorImpact
0
{-# INLINE lessErrDenomsP #-}
lessErrSimpleDecomp4PG :: ErrorImpact -> [Int] -> Double -> ([Integer], Double)
lessErrSimpleDecomp4PG :: ErrorImpact -> [ErrorImpact] -> Double -> ([Integer], Double)
lessErrSimpleDecomp4PG ErrorImpact
n [ErrorImpact]
ns Double
k =
let !ints :: [Integer]
ints = ErrorImpact -> [ErrorImpact] -> Double -> [Integer]
lessErrDenomsPG (- ErrorImpact
1) [ErrorImpact]
ns Double
k
!revs :: [Double]
revs = forall a b. (a -> b) -> [a] -> [b]
map (\Integer
t -> Double
1.0forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
t) [Integer]
ints
!s :: Double
s = forall a. Num a => [a] -> a
sum [Double]
revs
!err :: Double
err = Double
s forall a. Num a => a -> a -> a
- Double
k
!reverr :: Double
reverr = Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a. Num a => a -> a
abs Double
err
!next :: Integer
next
| ErrorImpact
n forall a. Ord a => a -> a -> Bool
> ErrorImpact
0 = forall a b. (RealFrac a, Integral b) => a -> b
truncate Double
reverr
| ErrorImpact
n forall a. Ord a => a -> a -> Bool
< ErrorImpact
0 = forall a b. (RealFrac a, Integral b) => a -> b
ceiling Double
reverr
| Bool
otherwise = forall a b. (RealFrac a, Integral b) => a -> b
round Double
reverr
!err4 :: Double
err4 = Double
err forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
next in ([Integer]
ints forall a. Monoid a => a -> a -> a
`mappend` [Integer
next], Double
err4)
lessErrSimpleDecomp5PG :: ErrorImpact -> [Int] -> Double -> ([Integer], Double)
lessErrSimpleDecomp5PG :: ErrorImpact -> [ErrorImpact] -> Double -> ([Integer], Double)
lessErrSimpleDecomp5PG ErrorImpact
n [ErrorImpact]
ns Double
k =
let (![Integer]
ints, !Double
err4) = ErrorImpact -> [ErrorImpact] -> Double -> ([Integer], Double)
lessErrSimpleDecomp4PG (- ErrorImpact
1) [ErrorImpact]
ns Double
k
!reverr :: Double
reverr = Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a. Num a => a -> a
abs Double
err4
!next :: Integer
next
| ErrorImpact
n forall a. Ord a => a -> a -> Bool
> ErrorImpact
0 = forall a b. (RealFrac a, Integral b) => a -> b
truncate Double
reverr
| ErrorImpact
n forall a. Ord a => a -> a -> Bool
< ErrorImpact
0 = forall a b. (RealFrac a, Integral b) => a -> b
ceiling Double
reverr
| Bool
otherwise = forall a b. (RealFrac a, Integral b) => a -> b
round Double
reverr
!err5 :: Double
err5 = Double
err4 forall a. Num a => a -> a -> a
+ Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
next in ([Integer]
ints forall a. Monoid a => a -> a -> a
`mappend` [Integer
next], Double
err5)
egyptianFractionDecomposition :: Double -> ([(Integer,Integer)], Double)
egyptianFractionDecomposition :: Double -> ([(Integer, Integer)], Double)
egyptianFractionDecomposition Double
k
| Double
k forall a. Ord a => a -> a -> Bool
> Double
2.0forall a. Fractional a => a -> a -> a
/Double
3.0 Bool -> Bool -> Bool
&& Double
k forall a. Ord a => a -> a -> Bool
<= Double
1.0 = let ([Integer]
ks, Double
err) = ErrorImpact -> [ErrorImpact] -> Double -> ([Integer], Double)
lessErrSimpleDecomp5PG ErrorImpact
0 [] (Double
k forall a. Num a => a -> a -> a
- Double
2.0forall a. Fractional a => a -> a -> a
/Double
3.0) in ((Integer
2,Integer
3) forall a. a -> [a] -> [a]
: forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. [a] -> [a]
cycle [Integer
1]) [Integer]
ks, Double
err)
| Bool
otherwise = let ([Integer]
ks, Double
err) = ErrorImpact -> [ErrorImpact] -> Double -> ([Integer], Double)
lessErrSimpleDecomp5PG ErrorImpact
0 [] Double
k in (forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. [a] -> [a]
cycle [Integer
1]) [Integer]
ks, Double
err)