/// <summary>
        ///
        /// </summary>
        /// <param name="sf">sin function</param>
        /// <param name="cf">cos function</param>
        /// <param name="sp">sin power</param>
        /// <param name="cp">cos power</param>
        /// <returns></returns>
        private static ExComp SinCosTrig(SinFunction sf, CosFunction cf, int sp, int cp, string dispStr, AlgebraComp dVar, ref EvalData pEvalData)
        {
            if (!sf.GetInnerEx().IsEqualTo(cf.GetInnerEx()))
                return null;
            bool spEven = sp % 2 == 0;
            bool cpEven = cp % 2 == 0;

            if (spEven && !cpEven)
            {
                // Use cos^2(x) = 1 - sin^2(x)
                ExComp subbedCos = PowOp.StaticCombine(
                    SubOp.StaticCombine(
                    ExNumber.GetOne(),
                    PowOp.StaticCombine(new SinFunction(cf.GetInnerEx()), new ExNumber(2.0))),
                    new ExNumber((cp - 1) / 2));

                subbedCos = MulOp.StaticCombine(cf, MulOp.StaticCombine(PowOp.StaticCombine(sf, new ExNumber(sp)), subbedCos));

                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + dispStr + " =  \\int ( " + WorkMgr.ToDisp(subbedCos) + " ) d" + dVar.ToDispString() + WorkMgr.EDM,
                    "Use the identity " + WorkMgr.STM + "cos^{2}(x)=1-sin^{2}(x)" + WorkMgr.EDM);

                return subbedCos;
            }
            else if (!spEven && cpEven)
            {
                // Using sin^2(x) = 1 - cos^2(x)
                ExComp subbedCos = PowOp.StaticCombine(
                    SubOp.StaticCombine(
                    ExNumber.GetOne(),
                    PowOp.StaticCombine(new CosFunction(sf.GetInnerEx()), new ExNumber(2.0))),
                    new ExNumber((sp - 1) / 2));

                subbedCos = MulOp.StaticCombine(sf, MulOp.StaticCombine(PowOp.StaticCombine(cf, new ExNumber(cp)), subbedCos));

                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + dispStr + " = \\int ( " + WorkMgr.ToDisp(subbedCos) + " ) d" + dVar.ToDispString() + WorkMgr.EDM,
                    "Use the identity " + WorkMgr.STM + "sin^{2}(x)=1-cos^{2}(x)" + WorkMgr.EDM);

                return subbedCos;
            }
            else if (spEven && cpEven)
            {
                // Using sin^2(x) = (1/2)(1-cos(2x))
                // Using cos^2(x) = (1/2)(1+cos(2x))
                ExComp sinSub = MulOp.StaticCombine(
                    AlgebraTerm.FromFraction(ExNumber.GetOne(), new ExNumber(2.0)),
                    SubOp.StaticCombine(ExNumber.GetOne(), new CosFunction(MulOp.StaticCombine(new ExNumber(2.0), sf.GetInnerEx()))));
                ExComp cosSub = MulOp.StaticCombine(
                    AlgebraTerm.FromFraction(ExNumber.GetOne(), new ExNumber(2.0)),
                    AddOp.StaticCombine(ExNumber.GetOne(), new CosFunction(MulOp.StaticCombine(new ExNumber(2.0), sf.GetInnerEx()))));
                ExComp finalEx = MulOp.StaticCombine(
                    PowOp.StaticCombine(sinSub, new ExNumber(sp / 2)),
                    PowOp.StaticCombine(cosSub, new ExNumber(cp / 2)));

                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + dispStr + "=" + WorkMgr.ToDisp(finalEx) + WorkMgr.EDM,
                    "Use the identities " + WorkMgr.STM + "sin^2(x)=\\frac{1}{2}(1-cos(2x))" + WorkMgr.EDM + " and " + WorkMgr.STM +
                    "cos^2(x)=\\frac{1}{2}(1+cos(2x))" + WorkMgr.EDM);

                return finalEx;
            }

            return null;
        }
            protected override Function ComputeDerivative(Variable variable)
            {
                if (sin == null)
                {
                    sin = new SinFunction(f, this);
                }

                return -sin * f.Derivative(variable);
            }
        private static ExComp GetIsSingleFunc(ExComp single, AlgebraComp dVar, ref EvalData pEvalData)
        {
            if (single is PowerFunction)
            {
                // Add one to the power and then divide by the power.
                PowerFunction pf = single as PowerFunction;

                if (pf.GetPower().IsEqualTo(ExNumber.GetNegOne()))
                {
                    ExComp pfBase = pf.GetBase();

                    if (pfBase is PowerFunction)
                    {
                        PowerFunction pfBasePf = pfBase as PowerFunction;
                        if (pfBasePf.GetPower().IsEqualTo(new ExNumber(0.5)) || pfBasePf.GetPower().IsEqualTo(AlgebraTerm.FromFraction(ExNumber.GetOne(), new ExNumber(2.0))))
                        {
                            // Is this arcsin or arccos?
                            ExComp compare = AddOp.StaticCombine(MulOp.Negate(PowOp.StaticCombine(dVar, new ExNumber(2.0))), ExNumber.GetOne()).ToAlgTerm().RemoveRedundancies(false);

                            ExComp useBase;
                            if (pfBasePf.GetBase() is AlgebraTerm)
                                useBase = (pfBasePf.GetBase() as AlgebraTerm).RemoveRedundancies(false);
                            else
                                useBase = pfBasePf.GetBase();

                            if (useBase.IsEqualTo(compare))
                            {
                                ASinFunction asin = new ASinFunction(dVar);
                                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(\\frac{1}{sqrt{1-" + dVar.ToDispString() + "^2}})\\d" + dVar.ToDispString() +
                                    "=" + asin.FinalToDispStr() + WorkMgr.EDM, "Use the common antiderivative.");
                                return asin;
                            }
                        }

                        // See if it is just the regular (1/x^(1/2)) or something like that.
                        if (IsDerivAcceptable(pfBasePf, dVar) && !pfBasePf.GetPower().ToAlgTerm().Contains(dVar))
                        {
                            ExComp power = MulOp.Negate(pfBasePf.GetPower());
                            ExComp powChange = AddOp.StaticCombine(power, ExNumber.GetOne());
                            if (powChange is AlgebraTerm)
                                powChange = (powChange as AlgebraTerm).CompoundFractions();

                            pfBasePf.SetPower(powChange);
                            return DivOp.StaticCombine(pfBasePf, powChange);
                        }
                    }

                    if (pfBase.IsEqualTo(AddOp.StaticCombine(ExNumber.GetOne(), PowOp.StaticCombine(dVar, new ExNumber(2.0)))))
                    {
                        ATanFunction atan = new ATanFunction(dVar);
                        pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(\\frac{1}{" + dVar.ToDispString() + "^2+1})\\d" + dVar.ToDispString() +
                            "=" + atan.FinalToDispStr() + WorkMgr.EDM, "Use the common antiderivative.");
                        return atan;
                    }
                }

                if (pf.GetBase().IsEqualTo(Constant.GetE()) && pf.GetPower().IsEqualTo(dVar))
                {
                    pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + pf.FinalToDispStr() + ")\\d" + dVar.ToDispString() +
                        "=" + pf.FinalToDispStr() + WorkMgr.EDM, "Use the common antiderivative.");
                    return pf;
                }
                else if (!pf.GetBase().ToAlgTerm().Contains(dVar) && pf.GetPower().IsEqualTo(dVar))
                {
                    ExComp finalEx = DivOp.StaticWeakCombine(pf, LogFunction.Ln(pf.GetBase()));
                    pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + pf.FinalToDispStr() + ")\\d" + dVar.ToDispString() +
                        "=" + finalEx.ToAlgTerm().FinalToDispStr() + WorkMgr.EDM, "Use the common antiderivative law.");

                    return finalEx;
                }

                if (pf.GetBase() is TrigFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger())
                {
                    int pow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    if (pow < 0)
                    {
                        // Convert to the reciprocal.
                        pf = new PowerFunction((pf.GetBase() as TrigFunction).GetReciprocalOf(), new ExNumber(-pow));
                    }
                }

                if (IsDerivAcceptable(pf, dVar) && !pf.GetPower().ToAlgTerm().Contains(dVar))
                {
                    // The special case for the power function anti-dervivative.
                    if (ExNumber.GetNegOne().IsEqualTo(pf.GetPower()))
                    {
                        pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + pf.FinalToDispStr() + ")\\d" + dVar.ToDispString() +
                            "=ln(|" + dVar + "|)" + WorkMgr.EDM, "This comes from the known derivative " + WorkMgr.STM +
                            "\\frac{d}{dx}ln(x)=\\frac{1}{x}" + WorkMgr.EDM);

                        // The absolute value function was removed here.
                        return LogFunction.Ln(dVar);
                    }

                    ExComp powChange = AddOp.StaticCombine(pf.GetPower(), ExNumber.GetOne());
                    if (powChange is AlgebraTerm)
                        powChange = (powChange as AlgebraTerm).CompoundFractions();

                    string changedPowStr = WorkMgr.ToDisp(AddOp.StaticWeakCombine(pf.GetPower(), ExNumber.GetOne()));
                    pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + WorkMgr.ToDisp(single) + ")\\d" + dVar.ToDispString() +
                        "=\\frac{" + dVar.ToDispString() + "^{" + changedPowStr + "}}{" + changedPowStr + "}" + WorkMgr.EDM,
                        "Use the power rule of antiderivatives.");

                    pf.SetPower(powChange);
                    return DivOp.StaticCombine(pf, powChange);
                }
                else if ((new ExNumber(2.0)).IsEqualTo(pf.GetPower()) && pf.GetBase() is TrigFunction && (pf.GetBase() as TrigFunction).GetInnerEx().IsEqualTo(dVar) &&
                    (pf.GetBase() is SecFunction || pf.GetBase() is CscFunction))
                {
                    ExComp ad = null;
                    if (pf.GetBase() is SecFunction)
                        ad = new TanFunction(dVar);
                    else if (pf.GetBase() is CscFunction)
                        ad = MulOp.Negate(new CotFunction(dVar));

                    if (ad != null)
                    {
                        pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + pf.FinalToDispStr() + ")\\d" + dVar.ToDispString() + "=" +
                            WorkMgr.ToDisp(ad) + WorkMgr.EDM, "Use the common antiderivative.");

                        return ad;
                    }
                }
                else if (pf.GetBase() is SinFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 == 0)
                {
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    SinFunction sf = pf.GetBase() as SinFunction;
                    ExComp subbed = MulOp.StaticCombine(
                        AlgebraTerm.FromFraction(ExNumber.GetOne(), new ExNumber(2.0)),
                        SubOp.StaticCombine(ExNumber.GetOne(), new CosFunction(MulOp.StaticCombine(new ExNumber(2.0), sf.GetInnerEx()))));

                    subbed = PowOp.StaticCombine(subbed, new ExNumber(iPow / 2));

                    pEvalData.GetWorkMgr().FromSides(pf, subbed,
                        "Use the trig identity " + WorkMgr.STM + "sin^{2}(x) = \\frac{1}{2}(1-cos(2x))" + WorkMgr.EDM);

                    return Integral.TakeAntiDeriv(subbed, dVar, ref pEvalData);
                }
                else if (pf.GetBase() is SinFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 != 0)
                {
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    SinFunction sf = pf.GetBase() as SinFunction;
                    ExComp finalEx = MulOp.StaticCombine(sf,
                        PowOp.StaticCombine(
                        SubOp.StaticCombine(
                        ExNumber.GetOne(),
                        PowOp.StaticCombine(new CosFunction(sf.GetInnerEx()), new ExNumber(2.0))),
                        new ExNumber((iPow - 1) / 2)));

                    pEvalData.GetWorkMgr().FromSides(pf, finalEx,
                        "Use the trig identity " + WorkMgr.STM + "sin^{2}(x) = \\frac{1}{2}(1-cos(2x))" + WorkMgr.EDM);

                    ExComp finalEval = Integral.TakeAntiDeriv(finalEx, dVar, ref pEvalData);
                    return finalEval;
                }
                else if (pf.GetBase() is CosFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 == 0)
                {
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    CosFunction cf = pf.GetBase() as CosFunction;
                    ExComp subbed = MulOp.StaticCombine(
                        AlgebraTerm.FromFraction(ExNumber.GetOne(), new ExNumber(2.0)),
                        AddOp.StaticCombine(ExNumber.GetOne(), new CosFunction(MulOp.StaticCombine(new ExNumber(2.0), cf.GetInnerEx()))));

                    subbed = PowOp.StaticCombine(subbed, new ExNumber(iPow / 2));

                    pEvalData.GetWorkMgr().FromSides(pf, subbed,
                        "Use the trig identity " + WorkMgr.STM + "cos^{2}(x) = \\frac{1}{2}(1+cos(2x))" + WorkMgr.EDM);

                    ExComp finalEval = Integral.TakeAntiDeriv(subbed, dVar, ref pEvalData);
                    return finalEval;
                }
                else if (pf.GetBase() is CosFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 != 0)
                {
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    CosFunction cf = pf.GetBase() as CosFunction;
                    ExComp finalEx = MulOp.StaticCombine(cf,
                        PowOp.StaticCombine(
                        SubOp.StaticCombine(
                        ExNumber.GetOne(),
                        PowOp.StaticCombine(new SinFunction(cf.GetInnerEx()), new ExNumber(2.0))),
                        new ExNumber((iPow - 1) / 2)));

                    pEvalData.GetWorkMgr().FromSides(pf, finalEx,
                        "Use the trig identity " + WorkMgr.STM + "cos^{2}(x) = \\frac{1}{2}(1+cos(2x))" + WorkMgr.EDM);

                    ExComp intEval = Integral.TakeAntiDeriv(finalEx, dVar, ref pEvalData);
                    return intEval;
                }
                else if (pf.GetBase() is CscFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 == 0)
                {
                    // In the form csc^n(x) where n is even.
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    CscFunction cf = pf.GetBase() as CscFunction;
                    ExComp finalEx = MulOp.StaticCombine(new PowerFunction(cf, new ExNumber(2.0)),
                        PowOp.StaticCombine(
                            AddOp.StaticCombine(
                                ExNumber.GetOne(),
                                new PowerFunction(new CotFunction(cf.GetInnerTerm()), new ExNumber(2.0))),
                            new ExNumber((iPow / 2) - 1)));

                    pEvalData.GetWorkMgr().FromSides(pf, finalEx,
                        "Use the trig identity " + WorkMgr.STM + "csc^2(x) = 1 + cot^2(x)" + WorkMgr.EDM);

                    ExComp intEval = Integral.TakeAntiDeriv(finalEx, dVar, ref pEvalData);
                    return intEval;
                }
                else if (pf.GetBase() is TanFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 == 0)
                {
                    // In the form tan^n where n is even.
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    if (iPow > 2)
                        return null;
                    TanFunction tf = pf.GetBase() as TanFunction;
                    ExComp finalEx = SubOp.StaticCombine(PowOp.StaticCombine(new SecFunction(tf.GetInnerTerm()), new ExNumber(2.0)), ExNumber.GetOne());

                    pEvalData.GetWorkMgr().FromSides(pf, finalEx,
                        "Use the trig identity " + WorkMgr.STM + "tan^2(x) = sec^2(x)-1" + WorkMgr.EDM);

                    ExComp intEval = Integral.TakeAntiDeriv(finalEx, dVar, ref pEvalData);
                    return intEval;
                }
                else if (pf.GetBase() is TanFunction && pf.GetPower() is ExNumber && (pf.GetPower() as ExNumber).IsRealInteger() &&
                    (int)((pf.GetPower() as ExNumber).GetRealComp()) > 1 && (int)((pf.GetPower() as ExNumber).GetRealComp()) % 2 != 0)
                {
                    // In the form tan^k where k is odd.
                    int iPow = (int)(pf.GetPower() as ExNumber).GetRealComp();
                    TanFunction tf = pf.GetBase() as TanFunction;

                    ExComp finalEx = PowOp.StaticCombine(
                        SubOp.StaticCombine(PowOp.StaticCombine(new SecFunction(tf.GetInnerTerm()), new ExNumber(2.0)), ExNumber.GetOne()),
                        new ExNumber((iPow - 1) / 2));

                    pEvalData.GetWorkMgr().FromSides(pf, finalEx,
                        "Use the trig identity " + WorkMgr.STM + "tan^2(x) = sec^2(x)-1" + WorkMgr.EDM);

                    ExComp intEval = Integral.TakeAntiDeriv(finalEx, dVar, ref pEvalData);
                    return intEval;
                }
            }
            else if (single is TrigFunction)
            {
                if (!IsDerivAcceptable(single, dVar))
                    return null;

                ExComp ad = null;
                if (single is SinFunction)
                {
                    ad = MulOp.Negate(new CosFunction(dVar));
                }
                else if (single is CosFunction)
                {
                    ad = new SinFunction(dVar);
                }
                else if (single is TanFunction)
                {
                    ad = LogFunction.Ln(new SecFunction(dVar));
                }
                else if (single is CscFunction)
                {
                    ad = LogFunction.Ln(SubOp.StaticCombine(new CscFunction(dVar), new CotFunction(dVar)));
                }
                else if (single is SecFunction)
                {
                    ad = LogFunction.Ln(SubOp.StaticCombine(new SecFunction(dVar), new TanFunction(dVar)));
                }
                else if (single is CotFunction)
                {
                    ad = LogFunction.Ln(new SinFunction(dVar));
                }

                if (ad == null)
                    return null;

                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + (single as TrigFunction).FinalToDispStr() + ")\\d" + dVar.ToDispString() + "=" + WorkMgr.ToDisp(ad) +
                    WorkMgr.EDM,
                    "Use the common antiderivative.");

                return ad;
            }

            return null;
        }
 public CosFunction(Function f, SinFunction sin)
 {
     this.f = f;
     this.sin = sin;
 }