private static ExComp SecTanTrig(SecFunction sf, TanFunction tf, int sp, int tp, AlgebraComp dVar,
            ref IntegrationInfo pIntInfo, ref EvalData pEvalData)
        {
            if (!sf.GetInnerEx().IsEqualTo(tf.GetInnerEx()))
                return null;

            bool spEven = sp % 2 == 0;
            bool tpEven = tp % 2 == 0;
            if (!spEven && tp == 1)
            {
                //ExComp[] gp = new ExComp[] { PowOp.StaticCombine(sf, new Number(sp - 1)), new AlgebraTerm(sf, new MulOp(), tf) };
                //return AttemptUSub(gp, dVar, ref pIntInfo, ref pEvalData);

                AlgebraComp subInVar = null;

                if (sf.Contains(new AlgebraComp("u")) || tf.Contains(new AlgebraComp("u")))
                {
                    if (sf.Contains(new AlgebraComp("w")) || tf.Contains(new AlgebraComp("u")))
                        subInVar = new AlgebraComp("v");
                    else
                        subInVar = new AlgebraComp("w");
                }
                else
                    subInVar = new AlgebraComp("u");

                string innerStr = "(" + WorkMgr.ToDisp(sf.GetInnerTerm()) + ")";
                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int \\sec^{" + (sp - 1).ToString() + "}" + innerStr +
                    "sec" + innerStr + "tan" + innerStr + " d" + dVar.ToDispString() + WorkMgr.EDM, "Split the term up.");

                ExComp subbedIn = PowOp.StaticCombine(subInVar, new ExNumber(sp - 1));
                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int " + subInVar.ToDispString() + "^{" + (sp - 1).ToString() + "} d" + subInVar.ToDispString() + WorkMgr.EDM,
                    "Make the substitution " + WorkMgr.STM + subInVar.ToDispString() + "=\\sec" + innerStr + ", d" + subInVar.ToDispString() +
                    "=sec" + innerStr + "tan" + innerStr + "d" + subInVar.ToDispString());
                ExComp antiDeriv = TakeAntiDerivativeVarGp(new ExComp[] { subbedIn }, subInVar, ref pIntInfo, ref pEvalData);

                AlgebraTerm subbedBack = antiDeriv.ToAlgTerm().Substitute(subInVar, sf);
                pEvalData.GetWorkMgr().FromSides(subbedBack, null, "Sub back in.");

                return subbedBack;
            }
            //else if (!spEven && tpEven && sp > 2)
            //{
            //    ExComp secSubed = PowOp.StaticCombine(
            //        AddOp.StaticCombine(
            //            Number.One,
            //            PowOp.StaticCombine(new TanFunction(sf.InnerEx), new Number(2.0))),
            //        new Number((sp - 2) / 2));
            //    ExComp[] gp = new ExComp[] { PowOp.StaticCombine(tf, new Number(tp)), secSubed, PowOp.StaticCombine(sf, new Number(2.0)) };
            //    return AttemptUSub(gp, dVar, ref pIntInfo, ref pEvalData);
            //}

            return null;
        }
        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;
        }