public Matrix <T> Transform(CoordTransform <T> newCoords, Matrix <T> res = null, bool everyCycleOfLength2 = false) { if (res == this) { return(InPlaceTransform(newCoords, everyCycleOfLength2)); } MakeOrValidate(newCoords.DimF(Rows, Cols), ref res); for (int r = 0; r < Rows; r++) { for (int c = 0; c < Cols; c++) { res[newCoords.CoordF(this, r, c)] = this[r, c]; } } return(res); }
// newCoords MUST permute the indices public Matrix <T> InPlaceTransform(CoordTransform <T> newCoords, bool everyCycleOfLength2 = false) { ValidateDimensions(this, newCoords.DimF(Rows, Cols), "InPlaceTransform(CoordTransform<T> newCoords, bool everyCycleOfLength2 = false)", "this"); if (!everyCycleOfLength2) { bool[,] completed = new bool[Rows, Cols]; // has to search through this. *HIGHLY* inefficient. FIX. //T[] cycleV = new T[Rows * Cols]; Pair <int>[] cycleC = new Pair <int> [Rows * Cols]; int cycleBegin = 0; int pos = 0; cycleC[0] = new Pair <int>(0, 0); while (pos < cycleC.Length) { Pair <int> nextCoords = newCoords.CoordF(this, cycleC[pos].x, cycleC[pos].y); if (cycleC[cycleBegin].x == nextCoords.x && cycleC[cycleBegin].y == nextCoords.y) { // Cycle through T temp1 = this[cycleC[pos]]; T temp2; for (int i = cycleBegin; i <= pos; i++) { Pair <int> cs = cycleC[i]; temp2 = this[cs]; this[cs] = temp1; temp1 = temp2; completed[cs.x, cs.y] = true; // mark transformed } int r = 0, c = 0; for (r = 0; r < Rows && completed[r, c]; r++) { for (c = 0; c < Cols && completed[r, c]; c++) { ; // Loop through until we find something not completed } } if (pos == cycleC.Length - 1) { break; } cycleBegin = pos++; cycleC[cycleBegin] = new Pair <int>(r, c); } else { cycleC[++pos] = nextCoords; } } } else { bool[,] completed = new bool[Rows, Cols]; for (int r = 0; r < Rows; r++) { for (int c = 0; c < Cols; c++) { if (!completed[r, c]) { Pair <int> otCoords = newCoords.CoordF(this, r, c); T temp = this[otCoords]; this[otCoords] = this[r, c]; this[r, c] = temp; completed[r, c] = true; // not strictly necessary, since we're about to move past it. completed[otCoords.x, otCoords.y] = true; } } } } return(this); }