/// <summary> /// Adds the specified sparse rows regarding defined multipliers. /// </summary> /// <param name="a1">The a1.</param> /// <param name="a2">The a2.</param> /// <param name="a1Coef">The a1 coef.</param> /// <param name="a2Coef">The a2 coef.</param> /// <returns> a1 * a1Coef + a2 * a2Coef</returns> public static SparseRow Add(SparseRow a1, SparseRow a2, double a1Coef, double a2Coef) { var buf = new SparseRow(a2.Size + a1.Size); //based on https://stackoverflow.com/a/12993675/1106889 //result = a1 * a1Coef + a2 * a2Coef; var c1 = 0; var c2 = 0; var i1s = a1.Indexes; var v1s = a1.Values; var l1 = a1.Size; var i2s = a2.Indexes; var v2s = a2.Values; var l2 = a2.Size; while (c1 < l1 && c2 < l2) { var i1 = i1s[c1]; var i2 = i2s[c2]; var v1 = v1s[c1]; var v2 = v2s[c2]; if (i1 > i2) { buf.Add(i2 /*or i1*/, v2 * a2Coef); c2++; } else if (i1 < i2) { buf.Add(i1, v1 * a1Coef); c1++; } else {//common var newValue = v1 * a1Coef + v2 * a2Coef; buf.Add(i1, newValue); c1++; c2++; } } return(buf); }
/// <summary> /// Eliminates the specified index of <see cref="eliminated"/> row by adding appropriated multiply of <see cref="eliminator"/> to it. /// </summary> /// <param name="eliminator">The eliminator row.</param> /// <param name="eliminated">The eliminated row.</param> /// <param name="eliminateIndex">The index of eliminated member.</param> /// <returns>Eliminated version of <see cref="eliminated"/></returns> public static SparseRow Eliminate(SparseRow eliminator, SparseRow eliminated, int eliminateIndex, double epsilon = 0) { var buf = new SparseRow(eliminated.Size + eliminator.Size); //based on https://stackoverflow.com/a/12993675/1106889 //result = eliminator * coef + eliminated double coef; { var t1 = Array.BinarySearch(eliminator.Indexes, 0, eliminator.Size, eliminateIndex); var t2 = Array.BinarySearch(eliminated.Indexes, 0, eliminated.Size, eliminateIndex); if (t1 < 0 || t2 < 0) { throw new Exception(); } coef = -eliminated.Values[t2] / eliminator.Values[t1]; } var c1 = 0; var c2 = 0; var i1s = eliminator.Indexes; var v1s = eliminator.Values; var l1 = eliminator.Size; var i2s = eliminated.Indexes; var v2s = eliminated.Values; var l2 = eliminated.Size; while (c1 < l1 && c2 < l2) { var i1 = i1s[c1]; var i2 = i2s[c2]; var v1 = v1s[c1]; var v2 = v2s[c2]; if (i1 > i2) { buf.Add(i2 /*or i1*/, v2); c2++; } else if (i1 < i2) { buf.Add(i1, v1 * coef); c1++; } else {//common if (i1 != i2) { throw new Exception(); } var newValue = v1 * coef + v2; if (i1 == eliminateIndex || Math.Abs(newValue) < epsilon) { //this is eliminated item, newValue should be zero and nothing to add if (Math.Abs(newValue) > 1e-6) { throw new Exception("wrong result"); } } else { buf.Add(i1, newValue); } c1++; c2++; } } //tail { for (; c1 < l1; c1++) { var i1 = i1s[c1]; var v1 = v1s[c1]; buf.Add(i1, v1 * coef); } for (; c2 < l2; c2++) { var i2 = i2s[c2]; var v2 = v2s[c2]; buf.Add(i2, v2); } } return(buf); }