{----- using interval polynomials -----}

plotSineCosine :: IO ()
plotSineCosine = 
    FV.plotFns 
        [
--         ("sin^2(x) + cos^2(x) = 1", 
--            [
--             (("sin(x)", FV.blue, False), sineX),
--             (("cos(x)", FV.blue, False), cosineX)
--             ,
--             (("sin^2(x)", FV.blue, False), sineX * sineX),
--             (("cos^2(x)", FV.blue, False), cosineX * cosineX),
--             (("sin^2(x) + cos^2(x)", FV.blue, False), sineX * sineX + cosineX * cosineX)
--            ]
--         )
--         ,
         ("over thick argument",
            [
             (("x", FV.black, False), x),
             (("x+1", FV.black, False), xp1),
             (("x+(y\\in[0,1])", FV.black, False), xThickParam),
             (("[x,x+1]", FV.black, False), xThick),
             (("sin(x)", FV.black, False), sineX),
             (("sin(x+1)", FV.black, False), sinOutEff effSinCos xp1),
             (("sin(x+(y\\in[0,1]))", FV.red, False), sinOutEff effSinCos xThickParam),
             (("sin([x,x+1])", FV.green, False), sinOutEff effSinCos xThick),
             (("cos(x)", FV.black, False), cosineX),
             (("cos(x+1)", FV.black, False), cosOutEff effSinCos xp1),
             (("cos([x+(y\\in[0,1])])", FV.red, False), cosOutEff effSinCos xThickParam)
            ]
         )
--         ,
--         ("sin(x^2)",
--            [
--             (("x*x", FV.black, False), x * x),
--             (("sin(x*x)", FV.red, False), sineXSqr)
--            ]
--         )
        ]
    where
    maxdeg = 20
    taylorDeg = 10
    
    sineX =
        sinOutEff effSinCos x
    cosineX =
        cosOutEff effSinCos x
    sineXSqr =
        sinOutEff effSinCos (x * x)

    xp1 = x + (one x)
    xThickParam = x + y
    xThick = x +| (Interval 0 1 :: DI)

    x :: Poly
    x = newProjection sizeLimits doms "x"
    y = newProjection sizeLimits doms "y"
    doms = 
        [
            ("x", Interval (0) 2)
            ,
            ("y", Interval (0) 1)
        ]

    -- indicators controlling the approximation effort:
    effSinCos =
        (sincosDefaultEffort sampleFn)
        {
            sincoseff_taylorDeg = taylorDeg -- Taylor approximation degree
        }

    sizeLimits = -- restrictions on the size of the polynomials
        defaultSizeLimits
        {
            ipolylimits_maxdeg = maxdeg, -- maximum degree
            ipolylimits_maxsize = 1000, -- maximum number of terms
            ipolylimits_effort =
                (ipolylimits_effort defaultSizeLimits)
                {
                    ipolyeff_evalMaxSplitSize = 2000
                } 
        }
        where
        defaultSizeLimits = (defaultIntPolySizeLimits sampleCoeff () 1)
    sampleCoeff = 0
    sampleFn = x
plotSineCosine :: IO ()
plotSineCosine = 
    FV.plotFns 
        [
--         ("sin^2(x) + cos^2(x) = 1", 
--            [
--             (("sin(x)", FV.blue, False), sineX),
--             (("cos(x)", FV.blue, False), cosineX)
--             ,
--             (("sin^2(x)", FV.blue, False), sineX * sineX),
--             (("cos^2(x)", FV.blue, False), cosineX * cosineX),
--             (("sin^2(x) + cos^2(x)", FV.blue, False), sineX * sineX + cosineX * cosineX)
--            ]
--         )
--         ,
         ("over thick argument",
            [
             (("x", FV.black, False), x),
             (("x+1", FV.black, False), xp1),
             (("x+(y\\in[0,1])", FV.black, False), xThickParam),
             (("[x,x+1]", FV.black, False), xThick),
             (("sin(x)", FV.black, False), sineX),
             (("sin(x+1)", FV.black, False), sinOutEff effSinCos xp1),
             (("sin(x+(y\\in[0,1]))", FV.red, False), sinOutEff effSinCos xThickParam),
             (("sin([x,x+1])", FV.green, False), sinOutEff effSinCos xThick),
             (("cos(x)", FV.black, False), cosineX),
             (("cos(x+1)", FV.black, False), cosOutEff effSinCos xp1),
             (("cos([x+(y\\in[0,1])])", FV.red, False), cosOutEff effSinCos xThickParam)
            ]
         )
--         ,
--         ("sin(x^2)",
--            [
--             (("x*x", FV.black, False), x * x),
--             (("sin(x*x)", FV.red, False), sineXSqr)
--            ]
--         )
        ]
    where
    maxdeg = 20
    taylorDeg = 10
    
    sineX =
        sinOutEff effSinCos x
    cosineX =
        cosOutEff effSinCos x
    sineXSqr =
        sinOutEff effSinCos (x * x)

    xp1 = x + (one x)
    xThickParam = x + y
    xThick = x +| (Interval 0 1 :: DI)

    x :: Poly
    x = newProjection sizeLimits doms "x"
    y = newProjection sizeLimits doms "y"
    doms = 
        [
            ("x", Interval (0) 2)
            ,
            ("y", Interval (0) 1)
        ]

    -- indicators controlling the approximation effort:
    effSinCos =
        (sincosDefaultEffort sampleFn)
        {
            sincoseff_taylorDeg = taylorDeg -- Taylor approximation degree
        }

    sizeLimits = -- restrictions on the size of the polynomials
        defaultSizeLimits
        {
            ipolylimits_maxdeg = maxdeg, -- maximum degree
            ipolylimits_maxsize = 1000, -- maximum number of terms
            ipolylimits_effort =
                (ipolylimits_effort defaultSizeLimits)
                {
                    ipolyeff_evalMaxSplitSize = 2000
                } 
        }
        where
        defaultSizeLimits = (defaultIntPolySizeLimits sampleCoeff () 1)
    sampleCoeff = 0
    sampleFn = x
plotSineCosine = 
    FV.plotFns 
        [
--         ("sin^2(x) + cos^2(x) = 1", 
--            [
--             (("sin(x)", FV.blue, False), sineX),
--             (("cos(x)", FV.blue, False), cosineX)
--             ,
--             (("sin^2(x)", FV.blue, False), sineX * sineX),
--             (("cos^2(x)", FV.blue, False), cosineX * cosineX),
--             (("sin^2(x) + cos^2(x)", FV.blue, False), sineX * sineX + cosineX * cosineX)
--            ]
--         )
--         ,
         ("over thick argument",
            [
             (("x", FV.black, False), x),
             (("x+1", FV.black, False), xp1),
             (("x+(y\\in[0,1])", FV.black, False), xThickParam),
             (("[x,x+1]", FV.black, False), xThick),
             (("sin(x)", FV.black, False), sineX),
             (("sin(x+1)", FV.black, False), sinOutEff effSinCos xp1),
             (("sin(x+(y\\in[0,1]))", FV.red, False), sinOutEff effSinCos xThickParam),
             (("sin([x,x+1])", FV.green, False), sinOutEff effSinCos xThick),
             (("cos(x)", FV.black, False), cosineX),
             (("cos(x+1)", FV.black, False), cosOutEff effSinCos xp1),
             (("cos([x+(y\\in[0,1])])", FV.red, False), cosOutEff effSinCos xThickParam)
            ]
         )
--         ,
--         ("sin(x^2)",
--            [
--             (("x*x", FV.black, False), x * x),
--             (("sin(x*x)", FV.red, False), sineXSqr)
--            ]
--         )
        ]
    where
    maxdeg = 20
    taylorDeg = 10
    
    sineX =
        sinOutEff effSinCos x
    cosineX =
        cosOutEff effSinCos x
    sineXSqr =
        sinOutEff effSinCos (x * x)

    xp1 = x + (one x)
    xThickParam = x + y
    xThick = x +| (Interval 0 1 :: DI)

    x :: Poly
    x = newProjection sizeLimits doms "x"
    y = newProjection sizeLimits doms "y"
    doms = 
        [
            ("x", Interval (0) 2)
            ,
            ("y", Interval (0) 1)
        ]

    -- indicators controlling the approximation effort:
    effSinCos =
        (sincosDefaultEffort sampleFn)
        {
            sincoseff_taylorDeg = taylorDeg -- Taylor approximation degree
        }

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