public CasExpr Add(CasExpr expr1, CasExpr expr2)
 {
     if (expr1.Poly2.PolyEquals(expr2.Poly2))
     {
         return(new CasExpr(CasPolynomial.PolySum(expr1.Poly1, expr2.Poly1), expr2.Poly2));
     }
     else
     {
         var p1    = CasPolynomial.PolyProd(expr1.Poly1, expr2.Poly2);
         var p2    = CasPolynomial.PolyProd(expr1.Poly2, expr2.Poly1);
         var num   = CasPolynomial.PolySum(p1, p2);
         var denom = CasPolynomial.PolyProd(expr1.Poly2, expr2.Poly2);
         return(new CasExpr(num, denom));
     }
 }
 // Result is null if solver fails
 public Tuple <CasExpr, CasVar> Solve(CasExpr expr, CasVar forV)
 {
     if (expr.Poly1.ContainsVar(forV) && expr.Poly2.ContainsVar(forV))
     {
         return(null);
     }
     if (!expr.Poly1.ContainsVar(forV) && !expr.Poly2.ContainsVar(forV))
     {
         return(null);
     }
     if (expr.Poly1.ContainsVar(forV) && !expr.Poly2.ContainsVar(forV))
     {
         List <CasTerm> zeroTerms = new List <CasTerm>();
         List <CasTerm> oneTerms  = new List <CasTerm>();
         foreach (var t in expr.Poly1.Terms)
         {
             if (!t.Variables.ContainsKey(forV))
             {
                 zeroTerms.Add(t);
             }
             else if (t.Variables[forV] == 1)
             {
                 oneTerms.Add(t);
             }
             else
             {
                 return(null);
             }
         }
         if (oneTerms.Count == 0)
         {
             return(null);
         }
         CasPolynomial polyZeros = new CasPolynomial();
         CasPolynomial polyOnes  = new CasPolynomial();
         foreach (var t in zeroTerms)
         {
             polyZeros.Terms.Add(t.CopyWithCoefficient(-1 * t.Coefficient));
         }
         foreach (var t in oneTerms)
         {
             polyOnes.Terms.Add(t.CopyWithCoefficient(t.Coefficient));
             t.Variables.Remove(forV);
         }
         var newVar  = NewVar();
         var newTerm = new CasTerm(1);
         newTerm.Variables[newVar] = 1;
         polyZeros.Terms.Add(newTerm);
         var resExpr = new CasExpr(CasPolynomial.PolyProd(polyZeros, expr.Poly2), polyOnes);
         return(new Tuple <CasExpr, CasVar>(resExpr, newVar));
     }
     else
     {
         List <CasTerm> zeroTerms = new List <CasTerm>();
         List <CasTerm> oneTerms  = new List <CasTerm>();
         foreach (var t in expr.Poly2.Terms)
         {
             if (!t.Variables.ContainsKey(forV))
             {
                 zeroTerms.Add(t);
             }
             else if (t.Variables[forV] == 1)
             {
                 oneTerms.Add(t);
             }
             else
             {
                 return(null);
             }
         }
         if (oneTerms.Count == 0)
         {
             return(null);
         }
         CasPolynomial polyZeros = new CasPolynomial();
         CasPolynomial polyOnes  = new CasPolynomial();
         var           newVar    = NewVar();
         foreach (var t in zeroTerms)
         {
             polyZeros.Terms.Add(t.CopyWithCoefficient(-1 * t.Coefficient));
             t.Variables[newVar] = 1;
         }
         foreach (var t in oneTerms)
         {
             polyOnes.Terms.Add(t.CopyWithCoefficient(t.Coefficient));
             t.Variables.Remove(forV);
             t.Variables[newVar] = 1;
         }
         var resExpr = new CasExpr(CasPolynomial.PolySum(polyZeros, expr.Poly2), polyOnes);
         return(new Tuple <CasExpr, CasVar>(resExpr, newVar));
     }
 }