コード例 #1
0
ファイル: ILIndexOffset.cs プロジェクト: wdxa/ILNumerics
		/// <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);
			} 
		}
コード例 #2
0
        /// <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);
            }
        }