/// <summary> /// Evaluates (maps) ILRange on my IndexOffsets and return shifted version. /// </summary> /// <param name="range">range object specifying the selection to be addressed /// relative to my indices. Range's dimensions may be the same size or less than my /// dimensions. If range is null, the full storage will be addressed. </param> /// <param name="shift">Number of dimensions to shift mapped range</param> /// <returns>Mapped ILIndexOffset object. It may be used for direct addressing the /// data positions inside the physical storage. </returns> /// <remarks>TODO : prevent the global offset inside physicalStorage, holded in the /// first dimensions of m_indexOffset /// to be shifted to another position if shift != 0!!!</remarks> public ILIndexOffset Map(ILRange range, int shift) { int [][] idx; try { // **************************** Map full storage *********************************** if (range == null) { if (shift == 0) // early exit return new ILIndexOffset (this); // return full shifted version bool stop = false; int addSingletonValue = 0; int nonSingletonDims = 0; int rngPos; int idxPos = m_idxOffset.Length - 1; idx = new int[m_idxOffset.Length][]; for (int d = m_idxOffset.Length; d-->0;) { rngPos = (d + shift) % m_idxOffset.Length; // recognize "second end" after shift -> remove non singleton dimensions if (rngPos == m_idxOffset.Length-1) stop = false; if (m_idxOffset[rngPos].Length == 1 && !stop) { // save singleton dimensions values for later sum addSingletonValue += m_idxOffset[rngPos][0]; } else { stop = true; nonSingletonDims++; idx[idxPos] = new int [m_idxOffset[rngPos].Length]; for (int i = 0; i < m_idxOffset[rngPos].Length; i++) { idx[idxPos][i] = m_idxOffset[rngPos][i]; } idxPos--; } } // move int[][] to start in case of non singleton dimensions beeing removed if (idx != null && idxPos >= 0) { int [][] tmp1 = new int[nonSingletonDims][]; System.Array.Copy(idx,idxPos+1,tmp1,0,nonSingletonDims); idx = tmp1; } // add (removed) singleton dimensions to first dimension if (addSingletonValue > 0 && idx != null && idx.Length > 0) { for (int d = idx[0].Length; d-->0;) { idx[0][d] += addSingletonValue; } } return new ILIndexOffset(idx,(int[])m_isRegularySpaced.Clone()); } } catch (Exception e) { throw new ILArgumentException ("error mapping ILRange to ILIndexOffset.",e); } if (range.NumberOfDimensions > m_idxOffset.Length) throw new ArgumentException("invalid range specification"); idx = new int[range.NumberOfDimensions][]; try { // **************************** Map ranged storage *********************************** bool stop = false; int addSingletonValue = 0; int nonSingletonDims = 0; int rngPos; int idxPos = range.NumberOfDimensions - 1; int [] regularSpacing = new int [range.NumberOfDimensions]; for (int d = range.NumberOfDimensions; d-->0;) { rngPos = (d + shift) % range.NumberOfDimensions; // recognize "second end" after shift -> remove non singleton dimensions if (rngPos == range.NumberOfDimensions-1) stop = false; if (range[rngPos].Length == 1 && !stop && range[rngPos,0] >= 0) { // save singleton dimensions values for later sum addSingletonValue += m_idxOffset[rngPos][range[rngPos,0]]; } else if (range[rngPos].Length == 1 && range[rngPos,0]<0 ) { #region full dimension addressed stop = true; nonSingletonDims++; if (rngPos == range.NumberOfDimensions-1 && -range[rngPos,0] > m_idxOffset[idxPos].Length-1) { // resulting array must be reshaped -> add trailing dimensions to last dimensions int curDimLen = m_idxOffset[rngPos].Length; int myDimsNr = m_idxOffset.Length; int limit = (-1)*range[rngPos,0]+1; int [] posArr = new int[m_idxOffset.Length]; int higherDims = 0; for (int i = rngPos; i < myDimsNr; i++) higherDims += m_idxOffset[i][posArr[i]]; idx[idxPos] = new int [limit]; int curPos = 0; int[] curidxOffsDim = m_idxOffset[rngPos]; while (curPos < limit) { // sum higher dims higherDims = 0; for (int i = rngPos +1; i < myDimsNr; i++) higherDims += m_idxOffset[i][posArr[i]]; // current dimension for (int i = 0; i < curDimLen; i++) { idx[idxPos][curPos++] = curidxOffsDim[i]+higherDims; } // increase higher dimensions int di = rngPos + 1; while (di < myDimsNr) { posArr[di]++; if (posArr[di] >= m_idxOffset[di].Length) { posArr[di++] = 0; } else { break; } } } // todo: it might be possible to determine, if result is regulary spaced. Simple case would be // to scan the entries while filling. But... regularSpacing[idxPos] = int.MinValue; } else { idx[idxPos] = new int [(-1) * range[rngPos,0] + 1]; for (int i = 0; i < idx[idxPos].Length; i++) { idx[idxPos][i] = m_idxOffset[rngPos][i]; } regularSpacing[idxPos] = (range.Spacing(rngPos) > int.MinValue && m_isRegularySpaced[rngPos] > int.MinValue) ? range.Spacing(rngPos) * m_isRegularySpaced[rngPos] : int.MinValue; } #endregion full dimension addressed idxPos--; } else { // arbitrary indices inside dimension stop = true; nonSingletonDims++; idx[idxPos] = new int [range[rngPos].Length]; if (rngPos == range.NumberOfDimensions - 1 && range.NumberOfDimensions < m_idxOffset.Length) { // allow for indices > dimlen for (int i = 0; i < range[rngPos].Length; i++) { int destVal = 0; int secIdx = range[rngPos,i]; for (int idxInd = rngPos; idxInd < m_idxOffset.Length;) { destVal += m_idxOffset[idxInd][secIdx % m_idxOffset[idxInd].Length]; secIdx /= m_idxOffset[idxInd++].Length; } if (secIdx > 0) throw new ILArgumentException("index " + range[rngPos,i].ToString() + " out of range for dimension " + d.ToString()); idx[idxPos][i] = destVal; } } else { // only indices in dimension range allowed for (int i = 0; i < range[rngPos].Length; i++) { int secIdx = range[rngPos,i]; idx[idxPos][i] = m_idxOffset[rngPos][secIdx]; } } regularSpacing[idxPos] = (range.Spacing(rngPos) > int.MinValue && m_isRegularySpaced[rngPos] > int.MinValue) ? range.Spacing(rngPos) * m_isRegularySpaced[rngPos] : int.MinValue; idxPos--; } } // move int[][] to start in case of non singleton dimensions beeing removed if (nonSingletonDims < 2) { // create matrix at least System.Diagnostics.Debug.Assert(false,"reference dimensions too small. At least 2 dimensions required."); if (nonSingletonDims == 0) { // range is 0D idx = new int[2][]; idx[0] = new int[1] { addSingletonValue }; idx[1] = new int[1] { 0 }; } else { // range is 1D int[][] tmp1 = new int[2][]; int size = idx[idxPos + 1].Length; tmp1[0] = new int[size]; for (int d = size; d-->0; ) tmp1[0][d] = idx[idxPos + 1][d]; tmp1[1] = new int[1] { addSingletonValue }; // öurhg! ugly hack ! idx = tmp1; } } else { if (idxPos >= 0) { int newLen = idx.Length - idxPos - 1; int[][] tmp1 = new int[newLen][]; System.Array.Copy(idx, idxPos + 1, tmp1, 0, newLen); idx = tmp1; int[] tmp2 = new int[newLen]; System.Array.Copy(regularSpacing, idxPos + 1, tmp2, 0, newLen); regularSpacing = tmp2; } if (addSingletonValue > 0 && idx.Length > 0) { for (int d = idx[0].Length; d-- > 0; ) { idx[0][d] += addSingletonValue; } } } return new ILIndexOffset(idx,regularSpacing); } catch (Exception e) { throw new ArgumentException ("Invalid Range specification:",e); } }
/// <summary> /// Evaluates (maps) ILRange on my IndexOffsets and return shifted version. /// </summary> /// <param name="range">range object specifying the selection to be addressed /// relative to my indices. Range's dimensions may be the same size or less than my /// dimensions. If range is null, the full storage will be addressed. </param> /// <param name="shift">Number of dimensions to shift mapped range</param> /// <returns>Mapped ILIndexOffset object. It may be used for direct addressing the /// data positions inside the physical storage. </returns> /// <remarks>TODO : prevent the global offset inside physicalStorage, holded in the /// first dimensions of m_indexOffset /// to be shifted to another position if shift != 0!!!</remarks> public ILIndexOffset Map(ILRange range, int shift) { int [][] idx; try { // **************************** Map full storage *********************************** if (range == null) { if (shift == 0) { // early exit return(new ILIndexOffset(this)); } // return full shifted version bool stop = false; int addSingletonValue = 0; int nonSingletonDims = 0; int rngPos; int idxPos = m_idxOffset.Length - 1; idx = new int[m_idxOffset.Length][]; for (int d = m_idxOffset.Length; d-- > 0;) { rngPos = (d + shift) % m_idxOffset.Length; // recognize "second end" after shift -> remove non singleton dimensions if (rngPos == m_idxOffset.Length - 1) { stop = false; } if (m_idxOffset[rngPos].Length == 1 && !stop) { // save singleton dimensions values for later sum addSingletonValue += m_idxOffset[rngPos][0]; } else { stop = true; nonSingletonDims++; idx[idxPos] = new int [m_idxOffset[rngPos].Length]; for (int i = 0; i < m_idxOffset[rngPos].Length; i++) { idx[idxPos][i] = m_idxOffset[rngPos][i]; } idxPos--; } } // move int[][] to start in case of non singleton dimensions beeing removed if (idx != null && idxPos >= 0) { int [][] tmp1 = new int[nonSingletonDims][]; System.Array.Copy(idx, idxPos + 1, tmp1, 0, nonSingletonDims); idx = tmp1; } // add (removed) singleton dimensions to first dimension if (addSingletonValue > 0 && idx != null && idx.Length > 0) { for (int d = idx[0].Length; d-- > 0;) { idx[0][d] += addSingletonValue; } } return(new ILIndexOffset(idx, (int[])m_isRegularySpaced.Clone())); } } catch (Exception e) { throw new ILArgumentException("error mapping ILRange to ILIndexOffset.", e); } if (range.NumberOfDimensions > m_idxOffset.Length) { throw new ArgumentException("invalid range specification"); } idx = new int[range.NumberOfDimensions][]; try { // **************************** Map ranged storage *********************************** bool stop = false; int addSingletonValue = 0; int nonSingletonDims = 0; int rngPos; int idxPos = range.NumberOfDimensions - 1; int [] regularSpacing = new int [range.NumberOfDimensions]; for (int d = range.NumberOfDimensions; d-- > 0;) { rngPos = (d + shift) % range.NumberOfDimensions; // recognize "second end" after shift -> remove non singleton dimensions if (rngPos == range.NumberOfDimensions - 1) { stop = false; } if (range[rngPos].Length == 1 && !stop && range[rngPos, 0] >= 0) { // save singleton dimensions values for later sum addSingletonValue += m_idxOffset[rngPos][range[rngPos, 0]]; } else if (range[rngPos].Length == 1 && range[rngPos, 0] < 0) { #region full dimension addressed stop = true; nonSingletonDims++; if (rngPos == range.NumberOfDimensions - 1 && -range[rngPos, 0] > m_idxOffset[idxPos].Length - 1) { // resulting array must be reshaped -> add trailing dimensions to last dimensions int curDimLen = m_idxOffset[rngPos].Length; int myDimsNr = m_idxOffset.Length; int limit = (-1) * range[rngPos, 0] + 1; int [] posArr = new int[m_idxOffset.Length]; int higherDims = 0; for (int i = rngPos; i < myDimsNr; i++) { higherDims += m_idxOffset[i][posArr[i]]; } idx[idxPos] = new int [limit]; int curPos = 0; int[] curidxOffsDim = m_idxOffset[rngPos]; while (curPos < limit) { // sum higher dims higherDims = 0; for (int i = rngPos + 1; i < myDimsNr; i++) { higherDims += m_idxOffset[i][posArr[i]]; } // current dimension for (int i = 0; i < curDimLen; i++) { idx[idxPos][curPos++] = curidxOffsDim[i] + higherDims; } // increase higher dimensions int di = rngPos + 1; while (di < myDimsNr) { posArr[di]++; if (posArr[di] >= m_idxOffset[di].Length) { posArr[di++] = 0; } else { break; } } } // todo: it might be possible to determine, if result is regulary spaced. Simple case would be // to scan the entries while filling. But... regularSpacing[idxPos] = int.MinValue; } else { idx[idxPos] = new int [(-1) * range[rngPos, 0] + 1]; for (int i = 0; i < idx[idxPos].Length; i++) { idx[idxPos][i] = m_idxOffset[rngPos][i]; } regularSpacing[idxPos] = (range.Spacing(rngPos) > int.MinValue && m_isRegularySpaced[rngPos] > int.MinValue) ? range.Spacing(rngPos) * m_isRegularySpaced[rngPos] : int.MinValue; } #endregion full dimension addressed idxPos--; } else { // arbitrary indices inside dimension stop = true; nonSingletonDims++; idx[idxPos] = new int [range[rngPos].Length]; if (rngPos == range.NumberOfDimensions - 1 && range.NumberOfDimensions < m_idxOffset.Length) { // allow for indices > dimlen for (int i = 0; i < range[rngPos].Length; i++) { int destVal = 0; int secIdx = range[rngPos, i]; for (int idxInd = rngPos; idxInd < m_idxOffset.Length;) { destVal += m_idxOffset[idxInd][secIdx % m_idxOffset[idxInd].Length]; secIdx /= m_idxOffset[idxInd++].Length; } if (secIdx > 0) { throw new ILArgumentException("index " + range[rngPos, i].ToString() + " out of range for dimension " + d.ToString()); } idx[idxPos][i] = destVal; } } else { // only indices in dimension range allowed for (int i = 0; i < range[rngPos].Length; i++) { int secIdx = range[rngPos, i]; idx[idxPos][i] = m_idxOffset[rngPos][secIdx]; } } regularSpacing[idxPos] = (range.Spacing(rngPos) > int.MinValue && m_isRegularySpaced[rngPos] > int.MinValue) ? range.Spacing(rngPos) * m_isRegularySpaced[rngPos] : int.MinValue; idxPos--; } } // move int[][] to start in case of non singleton dimensions beeing removed if (nonSingletonDims < 2) { // create matrix at least System.Diagnostics.Debug.Assert(false, "reference dimensions too small. At least 2 dimensions required."); if (nonSingletonDims == 0) { // range is 0D idx = new int[2][]; idx[0] = new int[1] { addSingletonValue }; idx[1] = new int[1] { 0 }; } else { // range is 1D int[][] tmp1 = new int[2][]; int size = idx[idxPos + 1].Length; tmp1[0] = new int[size]; for (int d = size; d-- > 0;) { tmp1[0][d] = idx[idxPos + 1][d]; } tmp1[1] = new int[1] { addSingletonValue }; // öurhg! ugly hack ! idx = tmp1; } } else { if (idxPos >= 0) { int newLen = idx.Length - idxPos - 1; int[][] tmp1 = new int[newLen][]; System.Array.Copy(idx, idxPos + 1, tmp1, 0, newLen); idx = tmp1; int[] tmp2 = new int[newLen]; System.Array.Copy(regularSpacing, idxPos + 1, tmp2, 0, newLen); regularSpacing = tmp2; } if (addSingletonValue > 0 && idx.Length > 0) { for (int d = idx[0].Length; d-- > 0;) { idx[0][d] += addSingletonValue; } } } return(new ILIndexOffset(idx, regularSpacing)); } catch (Exception e) { throw new ArgumentException("Invalid Range specification:", e); } }