{-# 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 (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

{-| 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
 
 - -}
setOfSolutionsG :: ErrorImpact -> Double -> [(Double, Double)]
setOfSolutionsG :: ErrorImpact -> Double -> [(Double, Double)]
setOfSolutionsG 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))) in
            if Integer
j Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
p then [(Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
j, let j1 :: Double
j1 = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
j in 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)) | Integer -> Bool
forall {a}. Integral a => a -> Bool
f Integer
j ] else [(Double
x, Double
xDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0)) | Double
x <- [Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
j..Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
p], Integer -> Bool
forall {a}. Integral a => a -> Bool
f (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
x)]
 | Bool
otherwise = []
              where g :: Double -> Double
g Double
y = 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
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)))
                    f :: a -> Bool
f a
y = case ErrorImpact
n of 
                            ErrorImpact
0 -> Bool
True
                            -1 -> Double -> Double
g (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0
                            ErrorImpact
_ -> Double -> Double
g (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0
{-# INLINE setOfSolutionsG #-}

setOfSolutions :: Double -> [(Double, Double)]
setOfSolutions :: Double -> [(Double, Double)]
setOfSolutions = ErrorImpact -> Double -> [(Double, Double)]
setOfSolutionsG ErrorImpact
0
{-# INLINE setOfSolutions #-}

-- | Partially defined function, if there is no solutions then returns a tuple of 'undefined'. Beter
-- to use 'suitable21'
suitable2 :: Double -> (Double,Double)
suitable2 :: Double -> (Double, Double)
suitable2 Double
k 
 | [(Double, Double)] -> Bool
forall a. [a] -> Bool
null [(Double, Double)]
xs = (Double
forall a. HasCallStack => a
undefined, Double
forall a. HasCallStack => a
undefined)
 | Bool
otherwise = ((Double, Double) -> (Double, Double) -> Ordering)
-> [(Double, Double)] -> (Double, Double)
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy (\(Double
_, Double
y1) (Double
_, Double
y2) -> Double -> Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Double -> Double
forall a. Num a => a -> a
abs (Double
y1 Double -> Double -> Double
forall a. Num 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
y1))) (Double -> Double
forall a. Num a => a -> a
abs (Double
y2 Double -> Double -> Double
forall a. Num 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
y2)))) [(Double, Double)]
xs
      where !xs :: [(Double, Double)]
xs = Double -> [(Double, Double)]
setOfSolutions Double
k
{-# 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
suitable21G :: ErrorImpact -> Double -> Maybe ([Double],Double)
suitable21G :: ErrorImpact -> Double -> Maybe ([Double], Double)
suitable21G ErrorImpact
n Double
k  
 | [(Double, Double)] -> Bool
forall a. [a] -> Bool
null [(Double, Double)]
xs = Maybe ([Double], Double)
forall a. Maybe a
Nothing
 | Bool
otherwise = let (!Double
a,!Double
b) = ((Double, Double) -> (Double, Double) -> Ordering)
-> [(Double, Double)] -> (Double, Double)
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy (\(Double
_, Double
y1) (Double
_, Double
y2) -> Double -> Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Double -> Double
forall a. Num a => a -> a
abs (Double
y1 Double -> Double -> Double
forall a. Num 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
y1))) (Double -> Double
forall a. Num a => a -> a
abs (Double
y2 Double -> Double -> Double
forall a. Num 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
y2)))) [(Double, Double)]
xs
    in ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Double
a,Double
b],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
a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0Double -> 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
b)))
      where !xs :: [(Double, Double)]
xs = ErrorImpact -> Double -> [(Double, Double)]
setOfSolutionsG 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
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 = Double
k Double -> Double -> Double
forall a. Num 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
c)
           in if Double
err Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
|| ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== ErrorImpact
0 Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0) Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
/= -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err 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
c], Double
k Double -> Double -> Double
forall a. Num 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
c)) 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
check3FracDecompPartialG :: ErrorImpact -> Bool -> Double -> Maybe ([Double],Double)
check3FracDecompPartialG :: ErrorImpact -> Bool -> Double -> Maybe ([Double], Double)
check3FracDecompPartialG ErrorImpact
n Bool
direction 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] 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 s2 :: Maybe ([Double], Double)
s2 = Double -> Maybe ([Double], Double)
suitable21 (Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u) 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
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> 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
b1) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u in
                                         if Double
err Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
|| ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== ErrorImpact
0 Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0) Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
/= -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0) then ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u,Double
a1,Double
b1],
                                              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
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> 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
b1) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u) else Maybe ([Double], Double)
forall a. Maybe a
Nothing
 | Bool
otherwise = Maybe ([Double], Double)
forall a. Maybe a
Nothing
{-# 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
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 s2 :: Maybe ([Double], Double)
s2 = Double -> Maybe ([Double], Double)
suitable21 (Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u) 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
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> 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
b1) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u in
                                         if Double
err Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
|| ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== ErrorImpact
0 Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
== -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0) Bool -> Bool -> Bool
|| (ErrorImpact
n ErrorImpact -> ErrorImpact -> Bool
forall a. Eq a => a -> a -> Bool
/= -ErrorImpact
1 Bool -> Bool -> Bool
&& Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0) then 
                                          ([Double], Double) -> Maybe ([Double], Double)
forall a. a -> Maybe a
Just ([Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u,Double
a1,Double
b1],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
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> 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
b1) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust Maybe Double
u) 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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
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,
if it is equal to -1 - the absolute error can be only negative, otherwise - only positive
-}
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 #-}