private static ExComp TakeAntiDerivativeVarGp(ExComp[] gp, AlgebraComp dVar, ref IntegrationInfo pIntInfo, ref EvalData pEvalData)
        {
            // For later make a method that makes the appropriate substitutions.
            // If the inside of a function isn't just a variable and the derivative
            // isn't variable, make the substitution.

            // Derivative of nothing is just the variable being integrated with respect to.
            if (gp.Length == 0)
            {
                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int\\d" + dVar.ToDispString() + "=" + dVar.ToDispString() + WorkMgr.EDM,
                    "Use the antiderivative power rule.");
                return dVar;
            }

            ExComp atmpt = null;

            // Is this a single function? (power included)
            if (gp.Length == 1 && gp[0] is AlgebraFunction)
            {
                if (gp[0] is PowerFunction)
                    gp[0] = (gp[0] as PowerFunction).ForceCombineExponents();

                atmpt = GetIsSingleFunc(gp[0], dVar, ref pEvalData);
                if (atmpt != null)
                {
                    pEvalData.AttemptSetInputType(InputType.IntBasicFunc);
                    return atmpt;
                }

                if (pIntInfo.ByPartsCount < IntegrationInfo.MAX_BY_PARTS_COUNT && (gp[0] is LogFunction || gp[0] is InverseTrigFunction))
                {
                    string thisStr = GroupHelper.ToAlgTerm(gp).FinalToDispStr();
                    pIntInfo.IncPartsCount();
                    atmpt = SingularIntByParts(gp[0], dVar, thisStr, ref pIntInfo, ref pEvalData);
                    if (atmpt != null)
                    {
                        pEvalData.AttemptSetInputType(InputType.IntParts);
                        return atmpt;
                    }
                }
            }
            else if (gp.Length == 1 && gp[0] is AlgebraComp)
            {
                pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "({0}^(1+1))/(1+1)=({0}^2)/(2)" + WorkMgr.EDM,
                    "Use the antiderivative power rule.", gp[0]);
                return AlgebraTerm.FromFraction(new PowerFunction(gp[0], new ExNumber(2.0)), new ExNumber(2.0));
            }
            else if (gp.Length == 2)      // Is this two functions multiplied together?
            {
                ExComp ad = null;
                // Are they two of the common antiderivatives?
                if (gp[0] is TrigFunction && gp[1] is TrigFunction && (gp[0] as TrigFunction).GetInnerEx().IsEqualTo(dVar) &&
                    (gp[0] as TrigFunction).GetInnerEx().IsEqualTo(dVar))
                {
                    if ((gp[0] is SecFunction && gp[1] is TanFunction) ||
                        (gp[0] is TanFunction && gp[1] is SecFunction))
                        ad = new SecFunction(dVar);
                    else if ((gp[0] is CscFunction && gp[1] is CotFunction) ||
                        (gp[0] is CotFunction && gp[1] is CscFunction))
                        ad = MulOp.Negate(new CscFunction(dVar));
                }

                if (ad != null)
                {
                    pEvalData.GetWorkMgr().FromFormatted(WorkMgr.STM + "\\int(" + gp[0].ToAlgTerm().FinalToDispStr() +
                        gp[1].ToAlgTerm().FinalToDispStr() + ")\\d" + dVar.ToDispString() + "=" +
                        ad.ToAlgTerm().FinalToDispStr() + WorkMgr.EDM,
                        "Use the common antiderivative.");
                    pEvalData.AttemptSetInputType(InputType.IntBasicFunc);
                    return ad;
                }
            }

            if (pIntInfo.USubCount < IntegrationInfo.MAX_U_SUB_COUNT)
            {
                pIntInfo.IncSubCount();
                atmpt = AttemptUSub(gp, dVar, ref pIntInfo, ref pEvalData);

                if (atmpt != null)
                {
                    pEvalData.AttemptSetInputType(InputType.IntUSub);
                    return atmpt;
                }
            }

            if (gp.Length == 1 || gp.Length == 2)
            {
                ExComp[] den = GroupHelper.GetDenominator(gp, false);
                if (den != null && den.Length == 1)
                {
                    ExComp[] num = GroupHelper.GetNumerator(gp);
                    if (num.Length == 1)
                    {
                        int prePFWorkStepCount = ArrayFunc.GetCount(pEvalData.GetWorkMgr().GetWorkSteps());
                        atmpt = AttemptPartialFractions(num[0], den[0], dVar, ref pIntInfo, ref pEvalData);
                        if (atmpt != null)
                            return atmpt;
                        pEvalData.GetWorkMgr().PopStepsCount(prePFWorkStepCount);
                    }
                }
            }

            // Trig substitutions.
            int prevTrigSubWorkCount = ArrayFunc.GetCount(pEvalData.GetWorkMgr().GetWorkSteps());
            atmpt = (new TrigSubTech()).TrigSubstitution(gp, dVar, ref pEvalData);
            if (atmpt != null)
                return atmpt;
            else
                pEvalData.GetWorkMgr().PopSteps(prevTrigSubWorkCount);

            if (gp.Length == 2)
            {
                // Using trig identities to make substitutions.
                atmpt = TrigFuncIntegration(gp[0], gp[1], dVar, ref pIntInfo, ref pEvalData);
                if (atmpt != null)
                    return atmpt;

                // Integration by parts.
                if (pIntInfo.ByPartsCount < IntegrationInfo.MAX_BY_PARTS_COUNT)
                {
                    int prevWorkStepCount = ArrayFunc.GetCount(pEvalData.GetWorkMgr().GetWorkSteps());
                    string thisStr = GroupHelper.ToAlgTerm(gp).FinalToDispStr();
                    pIntInfo.IncPartsCount();
                    // Is one of these a denominator because if so don't do integration by parts.
                    if (!(gp[0] is PowerFunction && (gp[0] as PowerFunction).IsDenominator()) && !(gp[1] is PowerFunction && (gp[1] as PowerFunction).IsDenominator()))
                    {
                        atmpt = IntByParts(gp[0], gp[1], dVar, thisStr, ref pIntInfo, ref pEvalData);
                        if (atmpt != null)
                        {
                            pEvalData.AttemptSetInputType(InputType.IntParts);
                            return atmpt;
                        }
                        else
                            pEvalData.GetWorkMgr().PopStepsCount(ArrayFunc.GetCount(pEvalData.GetWorkMgr().GetWorkSteps()) - prevWorkStepCount);
                    }
                }
            }

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