plotSineOfCosine :: IO ()
plotSineOfCosine =
    FV.plotFns 
        [
         ("sin(cos(x))",
            [
--             (("x", FV.black, False), x),
             (("cos(x)", FV.black, False), cosX)
             ,
             (("sin(cos(x))", FV.black, False), sinOutEff effSinCos2 cosX)
--             ,
--             (("1+eps1DI", FV.black, False), eps1DIp1)
--             ,
--             (("(1+ePI)cos(x)", FV.red, True), eps1PIcosX)
             ,
             (("(1+eDI)cos(x)", FV.green, True), eps1DIcosX)
--             ,
--             (("sin((1+ePI)cos(x))", FV.red, True), Interval poly_sinEps1CosX poly_sinEps1CosX)
             ,
             (("sin((1+eDI)cos(x))", FV.blue, True), sinEps1CosX)
            ]
         )
        ]
    where
    maxdeg = 12
    maxsize = 100
    taylorDeg1 = 15
    taylorDeg2 = 20
    bernsteinDeg = 2
    evalMaxSplitSize = 2000
-- best so far:
--    maxdeg = 12
--    maxsize = 100
--    taylorDeg1 = 15
--    taylorDeg2 = 20
--    bernsteinDeg = 2
--    evalMaxSplitSize = 2000
    
    
    sinEps1CosX = sinOutEff effSinCos2 eps1DIcosX
    poly_sinEps1CosX = sinOutEff poly_effSinCos2 poly_eps1cosX
    
    poly_eps1cosX = poly_eps1p1 * poly_cosX
    poly_eps1p1 = poly_eps1 +| (1 :: Int)

    eps1DIcosX = eps1DIp1 * cosX
    eps1DIp1 = newConstFn sizeLimits doms (eps1DI +| (1 :: Int))

    cosX = cosOutEff effSinCos1 x
    poly_cosX = cosOutEff poly_effSinCos1 poly_x

    poly_eps1 = newProjection sizeLimits doms "eps1" :: Poly
    poly_x = newProjection sizeLimits doms "x" :: Poly
    x = newProjection sizeLimits doms "x" :: PI
    doms =
        [
            ("x", 0 /\ 2)
            ,
            ("eps1", eps1DI)
--            ,
--            ("eps2", eps2DI)
        ]
    eps1DI = (-eps1) /\ eps1
    eps2DI = (-eps2) /\ eps2
    eps1 = 0.125 :: DI
    eps2 = 0.125 :: DI
    
    -- indicators controlling the approximation effort:
    effSinCos1 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }
    poly_effSinCos1 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }

    effSinCos2 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }
    poly_effSinCos2 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }

    sizeLimits = -- restrictions on the size of the polynomials
        defaultSizeLimits
        {
            ipolylimits_maxdeg = maxdeg, -- maximum degree
            ipolylimits_maxsize = maxsize, -- maximum number of terms
            ipolylimits_effort =
                (ipolylimits_effort defaultSizeLimits)
                {
                    ipolyeff_evalMaxSplitSize = evalMaxSplitSize,
                    ipolyeff_minmaxBernsteinDegree = bernsteinDeg
                } 
        }
        where
        defaultSizeLimits = (defaultIntPolySizeLimits sampleCoeff () 1)
    sampleCoeff = 0
    sampleFn = x



{----- using polynomial intervals -----}
plotSineOfCosine :: IO ()
plotSineOfCosine =
    FV.plotFns 
        [
         ("sin(cos(x))",
            [
--             (("x", FV.black, False), x),
             (("cos(x)", FV.black, False), cosX)
             ,
             (("sin(cos(x))", FV.black, False), sinOutEff effSinCos2 cosX)
--             ,
--             (("1+eps1DI", FV.black, False), eps1DIp1)
--             ,
--             (("(1+ePI)cos(x)", FV.red, True), eps1PIcosX)
             ,
             (("(1+eDI)cos(x)", FV.green, True), eps1DIcosX)
--             ,
--             (("sin((1+ePI)cos(x))", FV.red, True), Interval poly_sinEps1CosX poly_sinEps1CosX)
             ,
             (("sin((1+eDI)cos(x))", FV.blue, True), sinEps1CosX)
            ]
         )
        ]
    where
    maxdeg = 12
    maxsize = 100
    taylorDeg1 = 15
    taylorDeg2 = 20
    bernsteinDeg = 2
    evalMaxSplitSize = 2000
-- best so far:
--    maxdeg = 12
--    maxsize = 100
--    taylorDeg1 = 15
--    taylorDeg2 = 20
--    bernsteinDeg = 2
--    evalMaxSplitSize = 2000
    
    
    sinEps1CosX = sinOutEff effSinCos2 eps1DIcosX
    poly_sinEps1CosX = sinOutEff poly_effSinCos2 poly_eps1cosX
    
    poly_eps1cosX = poly_eps1p1 * poly_cosX
    poly_eps1p1 = poly_eps1 +| (1 :: Int)

    eps1DIcosX = eps1DIp1 * cosX
    eps1DIp1 = newConstFn sizeLimits doms (eps1DI +| (1 :: Int))

    cosX = cosOutEff effSinCos1 x
    poly_cosX = cosOutEff poly_effSinCos1 poly_x

    poly_eps1 = newProjection sizeLimits doms "eps1" :: Poly
    poly_x = newProjection sizeLimits doms "x" :: Poly
    x = newProjection sizeLimits doms "x" :: PI
    doms =
        [
            ("x", 0 /\ 2)
            ,
            ("eps1", eps1DI)
--            ,
--            ("eps2", eps2DI)
        ]
    eps1DI = (-eps1) /\ eps1
    eps2DI = (-eps2) /\ eps2
    eps1 = 0.125 :: DI
    eps2 = 0.125 :: DI
    
    -- indicators controlling the approximation effort:
    effSinCos1 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }
    poly_effSinCos1 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }

    effSinCos2 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }
    poly_effSinCos2 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }

    sizeLimits = -- restrictions on the size of the polynomials
        defaultSizeLimits
        {
            ipolylimits_maxdeg = maxdeg, -- maximum degree
            ipolylimits_maxsize = maxsize, -- maximum number of terms
            ipolylimits_effort =
                (ipolylimits_effort defaultSizeLimits)
                {
                    ipolyeff_evalMaxSplitSize = evalMaxSplitSize,
                    ipolyeff_minmaxBernsteinDegree = bernsteinDeg
                } 
        }
        where
        defaultSizeLimits = (defaultIntPolySizeLimits sampleCoeff () 1)
    sampleCoeff = 0
    sampleFn = x



{----- using polynomial intervals -----}
plotSineOfCosine =
    FV.plotFns 
        [
         ("sin(cos(x))",
            [
--             (("x", FV.black, False), x),
             (("cos(x)", FV.black, False), cosX)
             ,
             (("sin(cos(x))", FV.black, False), sinOutEff effSinCos2 cosX)
--             ,
--             (("1+eps1DI", FV.black, False), eps1DIp1)
--             ,
--             (("(1+ePI)cos(x)", FV.red, True), eps1PIcosX)
             ,
             (("(1+eDI)cos(x)", FV.green, True), eps1DIcosX)
--             ,
--             (("sin((1+ePI)cos(x))", FV.red, True), Interval poly_sinEps1CosX poly_sinEps1CosX)
             ,
             (("sin((1+eDI)cos(x))", FV.blue, True), sinEps1CosX)
            ]
         )
        ]
    where
    maxdeg = 12
    maxsize = 100
    taylorDeg1 = 15
    taylorDeg2 = 20
    bernsteinDeg = 2
    evalMaxSplitSize = 2000
-- best so far:
--    maxdeg = 12
--    maxsize = 100
--    taylorDeg1 = 15
--    taylorDeg2 = 20
--    bernsteinDeg = 2
--    evalMaxSplitSize = 2000
    
    
    sinEps1CosX = sinOutEff effSinCos2 eps1DIcosX
    poly_sinEps1CosX = sinOutEff poly_effSinCos2 poly_eps1cosX
    
    poly_eps1cosX = poly_eps1p1 * poly_cosX
    poly_eps1p1 = poly_eps1 +| (1 :: Int)

    eps1DIcosX = eps1DIp1 * cosX
    eps1DIp1 = newConstFn sizeLimits doms (eps1DI +| (1 :: Int))

    cosX = cosOutEff effSinCos1 x
    poly_cosX = cosOutEff poly_effSinCos1 poly_x

    poly_eps1 = newProjection sizeLimits doms "eps1" :: Poly
    poly_x = newProjection sizeLimits doms "x" :: Poly
    x = newProjection sizeLimits doms "x" :: PI
    doms =
        [
            ("x", 0 /\ 2)
            ,
            ("eps1", eps1DI)
--            ,
--            ("eps2", eps2DI)
        ]
    eps1DI = (-eps1) /\ eps1
    eps2DI = (-eps2) /\ eps2
    eps1 = 0.125 :: DI
    eps2 = 0.125 :: DI
    
    -- indicators controlling the approximation effort:
    effSinCos1 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }
    poly_effSinCos1 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg1 -- Taylor approximation degree
        }

    effSinCos2 =
        (sincosDefaultEffort x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }
    poly_effSinCos2 =
        (sincosDefaultEffort poly_x)
        {
            sincoseff_taylorDeg = taylorDeg2 -- Taylor approximation degree
        }

    sizeLimits = -- restrictions on the size of the polynomials
        defaultSizeLimits
        {
            ipolylimits_maxdeg = maxdeg, -- maximum degree
            ipolylimits_maxsize = maxsize, -- maximum number of terms
            ipolylimits_effort =
                (ipolylimits_effort defaultSizeLimits)
                {
                    ipolyeff_evalMaxSplitSize = evalMaxSplitSize,
                    ipolyeff_minmaxBernsteinDegree = bernsteinDeg
                } 
        }
        where
        defaultSizeLimits = (defaultIntPolySizeLimits sampleCoeff () 1)
    sampleCoeff = 0
    sampleFn = x



{----- using polynomial intervals -----}