/// <summary> /// Subtracts symbolic variable b from symbolic variable a /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static SymbolicVariable Subtract(SymbolicVariable a, SymbolicVariable b) { if (a == null || b == null) { return(null); } if (!a.DividedTerm.Equals(b.DividedTerm)) { SymbolicVariable a_b = a.Clone(); bool econsumed = false; if (a_b.ExtraTerms.Count > 0) { // find if in extra terms there is an equality of b into it for (int iet = 0; iet < a_b.ExtraTerms.Count; iet++) { if (a_b.ExtraTerms[iet].Term.DividedTerm.Equals(b.DividedTerm)) { a_b.ExtraTerms[iet].Term = Subtract(a_b.ExtraTerms[iet].Term, b); econsumed = true; break; } } } if (!econsumed) { // add in the extra terms var negative_b = b.Clone(); a_b.ExtraTerms.Add(new ExtraTerm { Term = negative_b, Negative = true }); } AdjustZeroCoeffecientTerms(ref a_b); return(a_b); } SymbolicVariable subB = b.Clone(); int sub = -1; SymbolicVariable sv = a.Clone(); NewPart: bool consumed = false; if (a.BaseEquals(subB)) { if (a.CoeffecientPowerTerm == null && subB.CoeffecientPowerTerm == null) { sv.Coeffecient = a.Coeffecient - subB.Coeffecient; consumed = true; } else if (a.CoeffecientPowerTerm != null && subB.CoeffecientPowerTerm != null) { if (a.CoeffecientPowerTerm.Equals(subB.CoeffecientPowerTerm)) { var cr = a.Coeffecient - subB.Coeffecient; if (cr == 0) { sv.Coeffecient = cr; consumed = true; } } } else { // nothing } } //so the equality doesn't exits or this instance have other terms also // there are two cases now // 1- the symbolic can be added to one of the existing terms (which will be perfect) // 2- there are no compatible term so we have to add it to the addedvariables of this instance. foreach (var av in a.AddedTerms) { if (av.Value.BaseEquals(subB)) { var iv = a.AddedTerms[av.Key].Clone(); if (iv.CoeffecientPowerTerm == null && subB.CoeffecientPowerTerm == null) { iv.Coeffecient = iv.Coeffecient - subB.Coeffecient; sv.AddedTerms[av.Key] = iv; consumed = true; } else if (iv.CoeffecientPowerTerm != null && subB.CoeffecientPowerTerm != null) { if (iv.CoeffecientPowerTerm.Equals(subB.CoeffecientPowerTerm)) { var cr = iv.Coeffecient - subB.Coeffecient; if (cr == 0) { iv.Coeffecient = cr; sv.AddedTerms[av.Key] = iv; consumed = true; } } } else { } } } if (!consumed) { // add it to the positive variables. SymbolicVariable pv; sv.AddedTerms.TryGetValue(subB.WholeValueBaseKey, out pv); if (pv == null) { pv = subB.Clone(); pv.Coeffecient *= -1; var SubTerms = pv._AddedTerms; // store them for later use. pv._AddedTerms = null; pv.DividedTerm = One; sv.AddedTerms.Add(pv.WholeValueBaseKey, pv); if (SubTerms != null) { //then add the value added terms if exist foreach (var at in pv.AddedTerms) { at.Value.Coeffecient *= -1; sv.AddedTerms.Add(at.Value.WholeValueBaseKey, at.Value); } } } else { //exist before add it to this variable. sv.AddedTerms[subB.WholeValueBaseKey] = Subtract(sv.AddedTerms[subB.WholeValueBaseKey], subB); } } if (b.AddedTerms.Count > 0) { sub = sub + 1; //increase if (sub < b.AddedTerms.Count) { // there are still terms to be consumed // this new term is a sub term in b and will be added to all terms of a. subB = b.AddedTerms.ElementAt(sub).Value; goto NewPart; } } // reaching here indicates that we didn't sum up the value to any of the target extra terms // so we need to include extra terms here if (b._ExtraTerms != null && b._ExtraTerms.Count > 0) { // add extra terms of b into sv foreach (var eb in b._ExtraTerms) { var eeb = eb.Clone(); if (eeb.Negative) { eeb.Negative = false; // -- == + } sv.ExtraTerms.Add(eeb); } } AdjustSpecialFunctions(ref sv); AdjustZeroPowerTerms(sv); AdjustZeroCoeffecientTerms(ref sv); return(sv); }
public static SymbolicVariable Divide(SymbolicVariable a, SymbolicVariable b) { if (a == null || b == null) { return(null); } SymbolicVariable SourceTerm = a.Clone(); // if the divided term is more than on term // x^2/(y-x) ==> if (b.AddedTerms.Count > 0 || (b._ExtraTerms != null && b._ExtraTerms.Count > 0)) { if (a.Equals(b)) { return(new SymbolicVariable("1")); } //multiply divided term by this value if (!a.IsZero) { SourceTerm.DividedTerm = Multiply(SourceTerm.DividedTerm, b); return(SourceTerm); } else { return(new SymbolicVariable("0")); } } SymbolicVariable TargetSubTerm = b.Clone(); TargetSubTerm._AddedTerms = null; // remove added variables to prevent its repeated calculations in second passes TargetSubTerm._ExtraTerms = null; // or to make sure nothing bad happens {my idiot design :S) if (a.BaseEquals(TargetSubTerm)) { #region symbols are equal (I mean 2*x^3 = 2*X^3) DivideCoeffecients(ref SourceTerm, TargetSubTerm); if (a.SymbolPowerTerm != null || TargetSubTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm = a.SymbolPowerTerm - TargetSubTerm.SymbolPowerTerm; } else { SourceTerm.SymbolPower = SourceTerm.SymbolPower - TargetSubTerm.SymbolPower; } //fuse the fused symbols in b into sv foreach (var bfv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key)) { SourceTerm.FusedSymbols[bfv.Key] -= bfv.Value; } else { SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value * -1); } } #endregion } else { #region Symbols are different if (string.IsNullOrEmpty(SourceTerm.Symbol)) { #region First Case: Source primary symbol doesn't exist // the instance have an empty primary variable so we should add it if (TargetSubTerm._BaseVariable != null) { SourceTerm._BaseVariable = TargetSubTerm._BaseVariable; } else { SourceTerm.Symbol = TargetSubTerm.Symbol; } SourceTerm.SymbolPower = -1 * TargetSubTerm.SymbolPower; if (TargetSubTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm = -1 * TargetSubTerm.SymbolPowerTerm.Clone(); } //fuse the fusedvariables in b into sv foreach (var bfv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key)) { SourceTerm.FusedSymbols[bfv.Key] -= bfv.Value; } else { SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value * -1); } } #endregion } else { if (SourceTerm.Symbol.Equals(TargetSubTerm.Symbol, StringComparison.OrdinalIgnoreCase)) { #region Second Case: Primary symbol in both source and target exist and equal if (SourceTerm._SymbolPowerTerm != null || TargetSubTerm._SymbolPowerTerm != null) { // make sure the object of symbol power term have values if they don't if (SourceTerm._SymbolPowerTerm == null) { // transfer the numerical power into symbolic variable mode SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm.SymbolPower.ToString(CultureInfo.InvariantCulture)); // also revert the original symbol power into 1 for validation after this SourceTerm.SymbolPower = 1; } if (TargetSubTerm._SymbolPowerTerm == null) { TargetSubTerm._SymbolPowerTerm = new SymbolicVariable(TargetSubTerm.SymbolPower.ToString(CultureInfo.InvariantCulture)); TargetSubTerm.SymbolPower = -1; // the target will always be dominator } SourceTerm._SymbolPowerTerm -= TargetSubTerm._SymbolPowerTerm; if (SourceTerm._SymbolPowerTerm.IsCoeffecientOnly) { SourceTerm._SymbolPower = SourceTerm._SymbolPowerTerm.Coeffecient; SourceTerm._SymbolPowerTerm = null; // remove it because we don't need symbolic when we reach co } else { // correct the source symbol power (because after division the power may still be positive if (SourceTerm._SymbolPowerTerm.IsNegative) { SourceTerm._SymbolPower = -1; SourceTerm._SymbolPowerTerm *= NegativeOne; } } } else { SourceTerm.SymbolPower -= TargetSubTerm.SymbolPower; } // also subtract the fused variables foreach (var fv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(fv.Key)) { SourceTerm.FusedSymbols[fv.Key] -= fv.Value; } else { SourceTerm.FusedSymbols.Add(fv.Key, fv.Value * -1); } } #endregion } else if (SourceTerm.FusedSymbols.ContainsKey(TargetSubTerm.Symbol)) { #region Third Case: Target primary symbol exist in source fused variables if (TargetSubTerm.SymbolPowerTerm != null) { SourceTerm.FusedSymbols[TargetSubTerm.Symbol] -= TargetSubTerm.SymbolPowerTerm; } else { SourceTerm.FusedSymbols[TargetSubTerm.Symbol] -= TargetSubTerm.SymbolPower; } // however primary symbol in source still the same so we need to add it to the value in target (if applicable) // also // there are still some fused variables in source that weren't altered by the target fused symbols // go through every symbol in fused symbols and add it to the source fused symbols foreach (var tfs in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(tfs.Key)) { // symbol exist so accumulate it SourceTerm._FusedSymbols[tfs.Key] -= tfs.Value; } else { // two cases here // 1 the fused key equal the primary symbol in source if (SourceTerm.Symbol.Equals(tfs.Key, StringComparison.OrdinalIgnoreCase)) { if (tfs.Value.SymbolicVariable != null) { if (SourceTerm._SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm -= tfs.Value.SymbolicVariable; } else { // sum the value in the numerical part to the value in symbolic part SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) - tfs.Value.SymbolicVariable; // reset the value in numerical part SourceTerm._SymbolPower = -1; } if (SourceTerm._SymbolPowerTerm.IsCoeffecientOnly) { SourceTerm._SymbolPower = SourceTerm._SymbolPowerTerm.Coeffecient; SourceTerm._SymbolPowerTerm = null; } } else { SourceTerm._SymbolPower -= tfs.Value.NumericalVariable; } } else { // 2 no matching at all which needs to add the symbol in target into the fused symbols in source. SourceTerm.FusedSymbols.Add(tfs.Key, tfs.Value * -1); } } } #endregion } else { #region Fourth Case: Target primary symbol doesn't exist in Source Primary Symbol nor Source Fused symbols // Add Target primary symbol to the fused symbols in source SourceTerm.FusedSymbols.Add( TargetSubTerm.Symbol, new HybridVariable { NumericalVariable = -1 * TargetSubTerm.SymbolPower, SymbolicVariable = TargetSubTerm.SymbolPowerTerm == null ? null : -1 * (SymbolicVariable)TargetSubTerm.SymbolPowerTerm }); // But the primary symbol of source may exist in the target fused variables. foreach (var fsv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(fsv.Key)) { SourceTerm.FusedSymbols[fsv.Key] -= fsv.Value; } else { // 1- if symbol is the same as priamry source if (SourceTerm.Symbol.Equals(fsv.Key, StringComparison.OrdinalIgnoreCase)) { if (fsv.Value.SymbolicVariable != null) { if (SourceTerm._SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm -= fsv.Value.SymbolicVariable; } else { // sum the value in the numerical part to the value in symbolic part SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) - fsv.Value.SymbolicVariable; // reset the value in numerical part SourceTerm._SymbolPower = -1; } } else { if (SourceTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm -= new SymbolicVariable(fsv.Value.ToString()); } else { SourceTerm._SymbolPower -= fsv.Value.NumericalVariable; } } } else { SourceTerm.FusedSymbols.Add(fsv.Key, fsv.Value * -1); } } } #endregion } } DivideCoeffecients(ref SourceTerm, TargetSubTerm); #endregion } if (SourceTerm.AddedTerms.Count > 0) { Dictionary <string, SymbolicVariable> newAddedVariables = new Dictionary <string, SymbolicVariable>(StringComparer.OrdinalIgnoreCase); foreach (var vv in SourceTerm.AddedTerms) { // get rid of divided term here because I already include it for the source term above var TSubTerm = TargetSubTerm.Numerator; var newv = Divide(vv.Value, TSubTerm); newAddedVariables.Add(newv.WholeValueBaseKey, newv); } SourceTerm._AddedTerms = newAddedVariables; } // Extra Terms of a if (SourceTerm.ExtraTerms.Count > 0) { List <ExtraTerm> newExtraTerms = new List <ExtraTerm>(); foreach (var et in SourceTerm.ExtraTerms) { var eterm = et.Term; if (et.Negative) { eterm = Multiply(NegativeOne, eterm); } var newe = Divide(eterm, TargetSubTerm); newExtraTerms.Add(new ExtraTerm { Term = newe }); } SourceTerm._ExtraTerms = newExtraTerms; } int subIndex = 0; SymbolicVariable total = SourceTerm; while (subIndex < b.AddedTerms.Count) { // we should multiply other parts also // then add it to the current instance // there are still terms to be consumed // this new term is a sub term in b and will be added to all terms of a. TargetSubTerm = b.AddedTerms.ElementAt(subIndex).Value.Clone(); TargetSubTerm.DividedTerm = b.DividedTerm; // this line is important because I extracted this added term from a bigger term with the same divided term // and when I did this the extracted term lost its divided term total = total + Divide(a, TargetSubTerm); subIndex = subIndex + 1; //increase } // for extra terms {terms that has different divided term} int extraIndex = 0; while (extraIndex < b.ExtraTerms.Count) { var eTerm = b.ExtraTerms[extraIndex]; TargetSubTerm = eTerm.Term; if (eTerm.Negative) { TargetSubTerm = Multiply(NegativeOne, TargetSubTerm); } var TargetTermSubTotal = Divide(a, TargetSubTerm); total = Add(total, TargetTermSubTotal); extraIndex++; } AdjustSpecialFunctions(ref total); AdjustZeroPowerTerms(total); AdjustZeroCoeffecientTerms(ref total); return(total); }
/// <summary> /// Multiply two symbolic variables /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static SymbolicVariable Multiply(SymbolicVariable a, SymbolicVariable b) { if (a == null || b == null) { return(null); } if (a.IsZero) { return(new SymbolicVariable("0")); } if (b.IsZero) { return(new SymbolicVariable("0")); } if (a.IsOne) { return(b.Clone()); } if (b.IsOne) { return(a.Clone()); } SymbolicVariable TargetSubTerm = b.Clone(); TargetSubTerm._AddedTerms = null; // remove added variables to prevent its repeated calculations in second passes TargetSubTerm._ExtraTerms = null; // remove the extra terms also // or to make sure nothing bad happens {my idiot design :S) SymbolicVariable SourceTerm = a.Clone(); if (a.BaseEquals(TargetSubTerm)) { #region Symbols are Equal (I mean 2*x^3 = 2*X^3) MultiplyCoeffecients(ref SourceTerm, TargetSubTerm); if (a.SymbolPowerTerm != null || TargetSubTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm = a.SymbolPowerTerm + TargetSubTerm.SymbolPowerTerm; } else { SourceTerm.SymbolPower = SourceTerm.SymbolPower + TargetSubTerm.SymbolPower; } //fuse the fused variables in b into sv foreach (var bfv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key)) { SourceTerm.FusedSymbols[bfv.Key] += bfv.Value; } else { SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value); } } #endregion } else { #region Symbols are Different if (string.IsNullOrEmpty(SourceTerm.Symbol)) { #region First Case: Source primary symbol doesn't exist // so take the primary symbol from the target into source // and copy the symbol power to it and symbolic power // // the instance have an empty primary variable so we should add it if (TargetSubTerm._BaseVariable != null) { SourceTerm._BaseVariable = TargetSubTerm._BaseVariable; } else { SourceTerm.Symbol = TargetSubTerm.Symbol; } SourceTerm.SymbolPower = TargetSubTerm.SymbolPower; if (TargetSubTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm = TargetSubTerm.SymbolPowerTerm.Clone(); } else { SourceTerm._SymbolPowerTerm = null; } //fuse the fused variables in target into source foreach (var fv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(fv.Key)) { SourceTerm.FusedSymbols[fv.Key] += fv.Value; } else { SourceTerm.FusedSymbols.Add(fv.Key, fv.Value); } } #endregion } else { #region Testing against symbol of targetsubterm if (SourceTerm.Symbol.Equals(TargetSubTerm.Symbol, StringComparison.OrdinalIgnoreCase)) { #region Second Case: Primary symbol in both source and target exist and equal // which means the difference is only in fused variables. // test for complex power (power that contains other symbolic variable) if (SourceTerm._SymbolPowerTerm != null || TargetSubTerm._SymbolPowerTerm != null) { // make sure the object of symbol power term have values if they don't if (SourceTerm._SymbolPowerTerm == null) { // transfer the numerical power into symbolic variable mode SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm.SymbolPower.ToString(CultureInfo.InvariantCulture)); // also revert the original symbol power into 1 for validation after this SourceTerm.SymbolPower = 1; } if (TargetSubTerm._SymbolPowerTerm == null) { TargetSubTerm._SymbolPowerTerm = new SymbolicVariable(TargetSubTerm.SymbolPower.ToString(CultureInfo.InvariantCulture)); TargetSubTerm.SymbolPower = 1; } // we used symbol power term SourceTerm._SymbolPowerTerm += TargetSubTerm._SymbolPowerTerm; } else { SourceTerm.SymbolPower += TargetSubTerm.SymbolPower; } // then add the fused variables foreach (var fv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(fv.Key)) { SourceTerm.FusedSymbols[fv.Key] += fv.Value; } else { SourceTerm.FusedSymbols.Add(fv.Key, fv.Value); } } #endregion } else if (SourceTerm.FusedSymbols.ContainsKey(TargetSubTerm.Symbol)) { #region Third Case: Target primary symbol exist in source fused variables // fill the source symbol in fused variables from the primary symbol in Target term. if (TargetSubTerm.SymbolPowerTerm != null) { SourceTerm.FusedSymbols[TargetSubTerm.Symbol] += new HybridVariable { NumericalVariable = TargetSubTerm.SymbolPower, SymbolicVariable = TargetSubTerm.SymbolPowerTerm } } ; else { SourceTerm.FusedSymbols[TargetSubTerm.Symbol] += TargetSubTerm.SymbolPower; } // however primary symbol in source still the same so we need to add it to the value in target // (if exist in fused variables in target) // also // there are still some fused variables in source that weren't altered by the target fused symbols // go through every symbol in fused symbols and add it to the source fused symbols foreach (var tfs in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(tfs.Key)) { // symbol exist so accumulate it SourceTerm._FusedSymbols[tfs.Key] += tfs.Value; } else { // two cases here // 1 the fused key equal the primary symbol in source if (SourceTerm.Symbol.Equals(tfs.Key, StringComparison.OrdinalIgnoreCase)) { if (tfs.Value.SymbolicVariable != null) { if (SourceTerm._SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm += tfs.Value.SymbolicVariable; } else { // sum the value in the numerical part to the value in symbolic part SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) + tfs.Value.SymbolicVariable; // reset the value in numerical part SourceTerm._SymbolPower = 1; } } else { SourceTerm._SymbolPower += tfs.Value.NumericalVariable; } } else { // 2 no matching at all which needs to add the symbol from target into the fused symbols in source. SourceTerm.FusedSymbols.Add(tfs.Key, tfs.Value); } } } #endregion } else { #region Fourth Case: Target primary symbol doesn't exist in Source Primary Symbol nor Source Fused symbols // Add Target primary symbol to the fused symbols in source SourceTerm.FusedSymbols.Add( TargetSubTerm.Symbol, new HybridVariable { NumericalVariable = TargetSubTerm.SymbolPower, SymbolicVariable = TargetSubTerm.SymbolPowerTerm == null ? null : TargetSubTerm.SymbolPowerTerm.Clone() }); // But the primary symbol of source may exist in the target fused variables. foreach (var fsv in TargetSubTerm.FusedSymbols) { if (SourceTerm.FusedSymbols.ContainsKey(fsv.Key)) { SourceTerm.FusedSymbols[fsv.Key] += fsv.Value; } else { // 1- if symbol is the same as priamry source if (SourceTerm.Symbol.Equals(fsv.Key, StringComparison.OrdinalIgnoreCase)) { if (fsv.Value.SymbolicVariable != null) { if (SourceTerm._SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm += fsv.Value.SymbolicVariable; } else { // sum the value in the numerical part to the value in symbolic part SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) + fsv.Value.SymbolicVariable; // reset the value in numerical part SourceTerm._SymbolPower = 1; } } else { if (SourceTerm.SymbolPowerTerm != null) { SourceTerm._SymbolPowerTerm += new SymbolicVariable(fsv.Value.ToString()); } else { SourceTerm._SymbolPower += fsv.Value.NumericalVariable; } } } else { SourceTerm.FusedSymbols.Add(fsv.Key, fsv.Value); } } } #endregion } #endregion } MultiplyCoeffecients(ref SourceTerm, TargetSubTerm); #endregion } if (SourceTerm.DividedTerm.IsOne) { SourceTerm.DividedTerm = TargetSubTerm.DividedTerm; } else { SourceTerm.DividedTerm = Multiply(SourceTerm.DividedTerm, TargetSubTerm.DividedTerm); } //here is a code to continue with other parts of a when multiplying them if (SourceTerm.AddedTerms.Count > 0) { Dictionary <string, SymbolicVariable> newAddedVariables = new Dictionary <string, SymbolicVariable>(StringComparer.OrdinalIgnoreCase); foreach (var vv in SourceTerm.AddedTerms) { // get rid of divided term here because I already include it for the source term above var TSubTerm = TargetSubTerm.Numerator; var newv = Multiply(vv.Value, TSubTerm); newAddedVariables.Add(newv.WholeValueBaseKey, newv); } SourceTerm._AddedTerms = newAddedVariables; } // Extra Terms of a if (SourceTerm.ExtraTerms.Count > 0) { List <ExtraTerm> newExtraTerms = new List <ExtraTerm>(); foreach (var et in SourceTerm.ExtraTerms) { var eterm = et.Term; if (et.Negative) { eterm = Multiply(NegativeOne, eterm); } var newe = Multiply(eterm, TargetSubTerm); newExtraTerms.Add(new ExtraTerm { Term = newe }); } SourceTerm._ExtraTerms = newExtraTerms; } // now source term which is the first parameter cloned, have the new calculated value. int subIndex = 0; SymbolicVariable total = SourceTerm; while (subIndex < b.AddedTerms.Count) { // we should multiply other parts also // then add it to the current instance // there are still terms to be consumed // this new term is a sub term in b and will be added to all terms of a. TargetSubTerm = b.AddedTerms.ElementAt(subIndex).Value.Clone(); TargetSubTerm.DividedTerm = b.DividedTerm; // this line is important because I extracted this added term from a bigger term with the same divided term // and when I did this the extracted term lost its divided term var TargetTermSubTotal = Multiply(a, TargetSubTerm); total = Add(total, TargetTermSubTotal); subIndex = subIndex + 1; //increase } // for extra terms {terms that has different divided term} int extraIndex = 0; while (extraIndex < b.ExtraTerms.Count) { var eTerm = b.ExtraTerms[extraIndex]; TargetSubTerm = eTerm.Term; if (eTerm.Negative) { TargetSubTerm = Multiply(NegativeOne, TargetSubTerm); } var TargetTermSubTotal = Multiply(a, TargetSubTerm); total = Add(total, TargetTermSubTotal); extraIndex++; } AdjustSpecialFunctions(ref total); AdjustZeroPowerTerms(total); AdjustZeroCoeffecientTerms(ref total); return(total); }