public static Object[][] SimplifySymbolicScalars(Object[][] A) { if (A == null) return null; // sort all arrays A[i] of A, and add the non-null ones in AL // also multiply all doubles ArrayList AL = new ArrayList(); { SimplifySymbolicScalarsComparer SSSC = new SimplifySymbolicScalarsComparer(); for (int i = 0; i < A.Length; i++) { if ((A[i] != null) && (A[i].Length > 0)) { Array.Sort(A[i], SSSC); // multiply doubles (at the front) if ((A[i].Length > 1) && (A[i][0] is Double) && (A[i][1] is Double)) // are there 2 or more Double at the front of A[i]? { // count number of doubles, multiply them together int nb = 2; // we know the first two are already double! double val = (double)A[i][0] * (double)A[i][1]; while ((nb < A[i].Length) && (A[i][nb] is Double)) { val *= (double)A[i][nb]; nb++; } // form a new array Object[] newAi = new Object[A[i].Length - nb + 1]; newAi[0] = val; Array.Copy(A[i], nb, newAi, 1, A[i].Length - nb); A[i] = newAi; } // if zero, then discard the whole thing: if (!((A[i].Length > 1) && (A[i][0] is Double) && ((double)A[i][0] == 0.0))) AL.Add(A[i]); } } } if (AL.Count == 1) return new Object[1][] {(Object[])AL[0] }; // sort the arrays themselves System.Collections.IComparer SSAC = new SimplifySymbolicArrayComparer(); AL.Sort(SSAC); // merge adjacent identical (up to scale) arrays ArrayList mergedAL = new ArrayList(); for (int i = 0; i < AL.Count;) // note: no increment { // find all arrays which are equal up to scale: int j = i+1; // j will become index of first array which is not equal up to scale while ((j < AL.Count) && (SSAC.Compare(AL[i], AL[j]) == 0)) j++; if (j - i > 1) { // at least one array equal up to scale: merge these arrays double scale = 0; // collect scale here int ALiFirstObjectIdx = -1; for (int k = i; k < j; k++) { int l = 0; Object[] ALk = (Object[])AL[k]; double ALkScale = 1.0; while ((l < ALk.Length) && (Object.ReferenceEquals(ALk[l].GetType(), DT))) { ALkScale *= (double)ALk[l]; l++; } if (k == i) ALiFirstObjectIdx = l; // remember where the Objects start in AL[i] scale += ALkScale; } if (scale != 0.0) { Object[] ALi = (Object[])AL[i]; bool scaleNotOne = (scale != 1.0); Object[] newALi = new Object[ALi.Length - ALiFirstObjectIdx + ((scaleNotOne) ? 1 : 0)]; if (scaleNotOne) newALi[0] = scale; Array.Copy(ALi, ALiFirstObjectIdx, newALi, (scaleNotOne) ? 1 : 0, ALi.Length - ALiFirstObjectIdx); mergedAL.Add(newALi); } i = j; } else { mergedAL.Add(AL[i]); i++; } } if (mergedAL.Count == 0) return null; Object[][] resultA = new Object[mergedAL.Count][]; for (int i = 0; i < mergedAL.Count; i++) resultA[i] = (Object[])mergedAL[i]; return resultA; }
public static Object[][] SimplifySymbolicScalars(Object[][] A) { if (A == null) { return(null); } // sort all arrays A[i] of A, and add the non-null ones in AL // also multiply all doubles ArrayList AL = new ArrayList(); { SimplifySymbolicScalarsComparer SSSC = new SimplifySymbolicScalarsComparer(); for (int i = 0; i < A.Length; i++) { if ((A[i] != null) && (A[i].Length > 0)) { Array.Sort(A[i], SSSC); // multiply doubles (at the front) if ((A[i].Length > 1) && (A[i][0] is Double) && (A[i][1] is Double)) // are there 2 or more Double at the front of A[i]? { // count number of doubles, multiply them together int nb = 2; // we know the first two are already double! double val = (double)A[i][0] * (double)A[i][1]; while ((nb < A[i].Length) && (A[i][nb] is Double)) { val *= (double)A[i][nb]; nb++; } // form a new array Object[] newAi = new Object[A[i].Length - nb + 1]; newAi[0] = val; Array.Copy(A[i], nb, newAi, 1, A[i].Length - nb); A[i] = newAi; } // if zero, then discard the whole thing: if (!((A[i].Length > 1) && (A[i][0] is Double) && ((double)A[i][0] == 0.0))) { AL.Add(A[i]); } } } } if (AL.Count == 1) { return new Object[1][] { (Object[])AL[0] } } ; // sort the arrays themselves System.Collections.IComparer SSAC = new SimplifySymbolicArrayComparer(); AL.Sort(SSAC); // merge adjacent identical (up to scale) arrays ArrayList mergedAL = new ArrayList(); for (int i = 0; i < AL.Count;) // note: no increment { // find all arrays which are equal up to scale: int j = i + 1; // j will become index of first array which is not equal up to scale while ((j < AL.Count) && (SSAC.Compare(AL[i], AL[j]) == 0)) { j++; } if (j - i > 1) { // at least one array equal up to scale: merge these arrays double scale = 0; // collect scale here int ALiFirstObjectIdx = -1; for (int k = i; k < j; k++) { int l = 0; Object[] ALk = (Object[])AL[k]; double ALkScale = 1.0; while ((l < ALk.Length) && (Object.ReferenceEquals(ALk[l].GetType(), DT))) { ALkScale *= (double)ALk[l]; l++; } if (k == i) { ALiFirstObjectIdx = l; // remember where the Objects start in AL[i] } scale += ALkScale; } if (scale != 0.0) { Object[] ALi = (Object[])AL[i]; bool scaleNotOne = (scale != 1.0); Object[] newALi = new Object[ALi.Length - ALiFirstObjectIdx + ((scaleNotOne) ? 1 : 0)]; if (scaleNotOne) { newALi[0] = scale; } Array.Copy(ALi, ALiFirstObjectIdx, newALi, (scaleNotOne) ? 1 : 0, ALi.Length - ALiFirstObjectIdx); mergedAL.Add(newALi); } i = j; } else { mergedAL.Add(AL[i]); i++; } } if (mergedAL.Count == 0) { return(null); } Object[][] resultA = new Object[mergedAL.Count][]; for (int i = 0; i < mergedAL.Count; i++) { resultA[i] = (Object[])mergedAL[i]; } return(resultA); }