{-# LANGUAGE BangPatterns, NoImplicitPrelude #-}

module UnitFractionsDecomposition2 where

import GHC.Base
import GHC.Num ((+),(-),(*),abs,Integer)
import GHC.List (null,last,head,length,filter)
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)

-- | Rounding to thousandth.
threeDigitsK :: Double -> Double
threeDigitsK :: Double -> Double
threeDigitsK Double
k = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
1000)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000.0
{-# INLINE threeDigitsK #-}

-- | Characterizes the impact of the absolute error sign on the approximation. 
type ErrorImpact = Int

-- | Absolute error with sign for the two unit fractions approximations and the first argument
--  (a in the related paper) being taken as the second parameter for the function. 
--  The second argument here  is expected to be 'fromIntegral' @a0@ where 'Data.List.elem' @a0@ @[2..] == @ 'True'.
absErr2Frac :: Double -> Double -> Double
absErr2Frac :: Double -> Double -> Double
absErr2Frac Double
k Double
y = Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
yDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0))) Double -> Double -> Double
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 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
u Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k
absErrUDecomp3 [Double
x,Double
y] Double
k =  Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k
absErrUDecomp3 [Double
x] Double
k = Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
x) Double -> Double -> Double
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 ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== ErrorImpact
0 Bool -> Bool -> Bool
|| ErrorImpact -> ErrorImpact -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ErrorImpact
n ErrorImpact
0 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Double -> Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Double -> Double -> Double
absErr2Frac Double
k (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y)) Double
0
{-# INLINE elemSolution2 #-}


{- | Searches for the minimum absolute error solution to two unit fractions decomposition 
 (approximation) for the fraction in the 'isRangeN' 'True' values with taking into account
the sign of the absolute error. 

If the 'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
setOfSolutionsGmin :: ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin :: ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin ErrorImpact
n Double
k 
 | Double -> Bool
isRangeN Double
k = 
    let j :: Integer
j = Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k)
        p :: Integer
p = Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
2.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k) ((Double -> Double
forall a. Floating a => a -> a
sqrt (Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
16) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
4)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
4Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
k)))
        j1 :: Double
j1 = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
j in
            if Integer
j Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
p 
                then if ErrorImpact -> Integer -> Double -> Bool
forall a. Integral a => ErrorImpact -> a -> Double -> Bool
elemSolution2 ErrorImpact
n Integer
j Double
k
                         then (Double
j1,Double
j1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
j1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0)) 
                         else (Double
0, -Double
1.0) 
                else (\Double
t -> if Double -> Double
forall a. Num a => a -> a
abs (Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0001) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.000001
                                then (Double
0, Double
0) 
                                else (Double
t, Double
tDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0))) (Double -> (Double, Double))
-> ([Double] -> Double) -> [Double] -> (Double, Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 
                                        (Double -> Double -> Double) -> Double -> [Double] -> Double
forall a b. (a -> b -> b) -> b -> [a] -> b
foldr (\Double
x Double
y -> if ErrorImpact -> Integer -> Double -> Bool
forall a. Integral a => ErrorImpact -> a -> Double -> Bool
elemSolution2 ErrorImpact
n (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
x) Double
k Bool -> Bool -> Bool
&& Double -> Double
forall a. Num a => a -> a
abs (Double -> Double -> Double
absErr2Frac Double
k Double
x) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Num a => a -> a
abs (Double -> Double -> Double
absErr2Frac Double
k Double
y) 
                                                           then Double
x 
                                                           else Double
y) (-Double
0.0001) ([Double] -> (Double, Double)) -> [Double] -> (Double, Double)
forall a b. (a -> b) -> a -> b
$ [Double
j1..Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
p]
 | Bool
otherwise = (Double
0, -Double
1.0)
{-# INLINE setOfSolutionsGmin #-}


-- | Searches for the minimum absolute error solution to two unit fractions decomposition 
-- (approximation) for the fraction in @k@ the 'isRangeN' @k = @ 'True'.
suitable2 :: Double -> (Double,Double)
suitable2 :: Double -> (Double, Double)
suitable2 = ErrorImpact -> Double -> (Double, Double)
setOfSolutionsGmin ErrorImpact
0
{-# INLINE suitable2 #-}

{- | Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
suitable21G :: ErrorImpact -> Double -> Maybe ([Double],Double)
suitable21G :: ErrorImpact -> Double -> Maybe ([Double], Double)
suitable21G ErrorImpact
n Double
k = 
   if Double -> Double
forall a. Num a => a -> a
abs Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.000001 
       then Maybe ([Double], Double)
forall a. Maybe a
Nothing 
       else ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Double
x, Double
y], Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
y) Double -> Double -> Double
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 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0.9
{-# INLINE isRangeN #-}

-- | The preferable range of the argument for 'suitable2' and 'suitable21' functions. For arguments
-- in this range the functions always have informative results.
isRangeNPref :: Double -> Bool
isRangeNPref :: Double -> Bool
isRangeNPref Double
k = Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< (Double
2.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
3.0)
{-# INLINE isRangeNPref #-}

{- | Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
check1FracDecompG :: ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG :: ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG ErrorImpact
n Double
k 
 | Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0.501 = 
     let c :: Double
c = (Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
k)
         err :: Double
err = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
c) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k
           in if Double
err Double -> Double -> Double
forall a. Num a => a -> a -> a
* ErrorImpact -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ErrorImpact
n Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0  
                  then let cs :: [Double]
cs = [Double
c] in ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Double]
cs, [Double] -> Double -> Double
absErrUDecomp3 [Double]
cs Double
k) 
                  else Maybe ([Double], Double)
forall a. Maybe a
Nothing
 | Bool
otherwise = Maybe ([Double], Double)
forall a. Maybe a
Nothing
{-# INLINE check1FracDecompG #-}

{- | Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
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 #-}

{- | Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign, 
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
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 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
1 = 
     let u :: Maybe Double
u = (\[Double]
us -> if [Double] -> Bool
forall a. [a] -> Bool
null [Double]
us 
                         then Maybe Double
forall a. Maybe a
Nothing 
                         else Double -> Maybe Double
forall a. a -> Maybe a
Just (if Bool
direction then [Double] -> Double
forall a. [a] -> a
last [Double]
us else [Double] -> Double
forall a. [a] -> a
head [Double]
us)) ([Double] -> Maybe Double)
-> ([Double] -> [Double]) -> [Double] -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Double
t -> let w :: Double
w = Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
t in 
                            Double
w Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0.005 Bool -> Bool -> Bool
&& Double
w Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= (Double
2.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
3.0)) ([Double] -> Maybe Double) -> [Double] -> Maybe Double
forall a b. (a -> b) -> a -> b
$ [Double
2.0..Double
10.0] [Double] -> [Double] -> [Double]
forall a. Monoid a => a -> a -> a
`mappend` (ErrorImpact -> Double) -> [ErrorImpact] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map ErrorImpact -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral [ErrorImpact]
ns in 
                               if Maybe Double -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Double
u 
                                   then Maybe ([Double], Double)
forall a. Maybe a
Nothing 
                                   else let u1 :: Double
u1 = Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u in let s2 :: Maybe ([Double], Double)
s2 = Double -> Maybe ([Double], Double)
suitable21 (Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
u1) in 
                                           if Maybe ([Double], Double) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe ([Double], Double)
s2 
                                               then Maybe ([Double], Double)
forall a. Maybe a
Nothing 
                                               else let ([Double
a1,Double
b1],Double
_) = Maybe ([Double], Double) -> ([Double], 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 Double -> Double -> Double
forall a. Num a => a -> a -> a
* ErrorImpact -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ErrorImpact
n Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0  
                                                           then ([Double], Double) -> Maybe ([Double], Double)
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 Maybe ([Double], Double)
forall a. Maybe a
Nothing
 | Bool
otherwise = Maybe ([Double], Double)
forall a. Maybe a
Nothing
{-# INLINE check3FracDecompPartialPG #-}

{- | Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
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 [([Double], Double)] -> Bool
forall a. [a] -> Bool
null [([Double], Double)]
ts 
              then (ErrorImpact
0,Maybe ([Double], Double)
forall a. Maybe a
Nothing,-Double
1.0) 
              else let p :: ([Double], Double)
p = (([Double], Double) -> ([Double], Double) -> Ordering)
-> [([Double], Double)] -> ([Double], Double)
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy ((([Double], Double) -> Double)
-> ([Double], Double) -> ([Double], Double) -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Double -> Double
forall a. Num a => a -> a
abs (Double -> Double)
-> (([Double], Double) -> Double) -> ([Double], Double) -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Double], Double) -> Double
forall a b. (a, b) -> b
snd)) [([Double], Double)]
ts in ([Double] -> ErrorImpact
forall a. [a] -> ErrorImpact
length (([Double], Double) -> [Double]
forall a b. (a, b) -> a
fst ([Double], Double)
p), ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Double], Double)
p, ([Double], Double) -> Double
forall a b. (a, b) -> b
snd ([Double], Double)
p))  ([([Double], Double)]
 -> (ErrorImpact, Maybe ([Double], Double), Double))
-> ([Maybe ([Double], Double)] -> [([Double], Double)])
-> [Maybe ([Double], Double)]
-> (ErrorImpact, Maybe ([Double], Double), Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 
                              [Maybe ([Double], Double)] -> [([Double], Double)]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe ([Double], Double)]
 -> (ErrorImpact, Maybe ([Double], Double), Double))
-> [Maybe ([Double], Double)]
-> (ErrorImpact, Maybe ([Double], Double), Double)
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]

{-| Allows to take  into account the sign of the absolute error of the aproximation. If the 
'ErrorImpact' parameter is equal to 0 , then absolute error can be of any sign,
otherwise the sign of it is the same as the sign of the 'ErrorImpact' argument.
-}
lessErrDenomsPG :: ErrorImpact -> [Int] -> Double -> [Integer]
lessErrDenomsPG :: ErrorImpact -> [ErrorImpact] -> Double -> [Integer]
lessErrDenomsPG ErrorImpact
n [ErrorImpact]
ns = 
  (\(ErrorImpact
_,Maybe ([Double], Double)
ks,Double
_) -> if Maybe ([Double], Double) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe ([Double], Double)
ks 
                    then [] 
                    else (Double -> Integer) -> [Double] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round ([Double] -> [Integer])
-> (Maybe ([Double], Double) -> [Double])
-> Maybe ([Double], Double)
-> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Double], Double) -> [Double]
forall a b. (a, b) -> a
fst (([Double], Double) -> [Double])
-> (Maybe ([Double], Double) -> ([Double], Double))
-> Maybe ([Double], Double)
-> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ([Double], Double) -> ([Double], Double)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ([Double], Double) -> [Integer])
-> Maybe ([Double], Double) -> [Integer]
forall a b. (a -> b) -> a -> b
$ Maybe ([Double], Double)
ks) ((ErrorImpact, Maybe ([Double], Double), Double) -> [Integer])
-> (Double -> (ErrorImpact, Maybe ([Double], Double), Double))
-> Double
-> [Integer]
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 #-}

--------------------------------------------

-- | Tries to approximate the fraction by just one unit fraction. Can be used for the numbers
-- between 0.005 and 0.501.
check1FracDecomp :: Double -> Maybe ([Double], Double)
check1FracDecomp :: Double -> Maybe ([Double], Double)
check1FracDecomp = ErrorImpact -> Double -> Maybe ([Double], Double)
check1FracDecompG ErrorImpact
0
{-# INLINE check1FracDecomp #-}

{- | Function to find the less by absolute value error approximation. One of the denominators is
taken from the range [2..10]. The two others are taken from the appropriate 'suitable21' 
applicattion.
-}
check3FracDecompPartial :: Bool -> Double -> Maybe ([Double],Double)
check3FracDecompPartial :: Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartial = ErrorImpact -> Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartialG ErrorImpact
0
{-# INLINE check3FracDecompPartial #-}

{- | Extended version of the 'check3FracDecompPartial' with the first denominator being taken not
 - only from the [2..10], but also from the custom user provided list. 
 - -}
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

-- | Returns a list of denominators for fraction decomposition using also those ones from the the list provided as the first argument. Searches for the least error from the checked ones.
lessErrDenomsP :: [Int] -> Double -> [Integer]
lessErrDenomsP :: [ErrorImpact] -> Double -> [Integer]
lessErrDenomsP = ErrorImpact -> [ErrorImpact] -> Double -> [Integer]
lessErrDenomsPG ErrorImpact
0
{-# INLINE lessErrDenomsP #-}