/// <summary> /// maximum /// </summary> /// <param name="A">input array, N-dimensional</param> /// <param name="I">return value. If this is an instance of an ILArray /// (f.e. 'empty'), on return I will hold the indices into leadDim of /// the maximum values. If, on entering the function, I is null, those indices /// will not be computed and I will be ignored.</param> /// <param name="leadDim">index of dimension to operate along</param> /// <returns>ILArray of type double. If I was empty having the dimension 'leadDim' /// reduced to 1 and holding maximum values </returns> public static /*!HC:ToutCls*/ ILArray<double> max(/*!HC:TinCls*/ ILArray<double> A, ref /*!HC:TindCls*/ ILArray<double> I, int leadDim) { if (A.IsEmpty) { if (!object.Equals (I,null)) I = /*!HC:TindCls*/ ILArray<double> .empty(0,0); return /*!HC:ToutCls*/ ILArray<double> .empty(A.Dimensions); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); if (leadDim == newDims.Length || inDim[leadDim] == 1) // scalar or sum over singleton -> return copy return (/*!HC:ToutCls*/ ILArray<double> )A.Clone(); int newLength; newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; /*!HC:ToutArr*/ double [] retSystemArr; retSystemArr = new /*!HC:ToutArr*/ double [newLength]; int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; #region HYCALPER GLOBAL_INIT /*!HC:TinArr*/ double result; /*!HC:TinArr*/ double curval; /*!HC:TindArr*/ double [] indices = null; bool createIndices = false; if (!Object.Equals(I,null)) { indices = new /*!HC:TindArr*/ double [retSystemArr.Length]; createIndices = true; } #endregion HYCALPER GLOBAL_INIT #region HYCALPER INIT_COMPLEX #endregion HYCALPER INIT_COMPLEX // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:TinArr*/ double * lastElement; /*!HC:ToutArr*/ double * tmpOut = pOutArr; /*!HC:TinArr*/ double * tmpIn = pInArr; if (createIndices) { /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; #region HYCALPER PRELOOP result = /*!HC:LIMITS*/ double.MinValue; #endregion HYCALPER PRELOOP while (tmpIn < lastElement) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(tmpIn - (lastElement - leadDimLen)); } tmpIn++; } *(tmpOut++) = (/*!HC:ToutArr*/ double )result; tmpInd++; } } else { /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; #region HYCALPER PRELOOP result = /*!HC:LIMITS*/ double.MinValue; #endregion HYCALPER PRELOOP while (tmpIn < lastElement) { curval = *tmpIn++; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } } #region HYCALPER POSTLOOP *(tmpOut++) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP } } } } #endregion physical along 1st leading dimension } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:ToutArr*/ double * lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements -1; /*!HC:TinArr*/ double * lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); /*!HC:ToutArr*/ double * tmpOut = pOutArr; int outLength = newLength - 1; /*!HC:TinArr*/ double * leadEnd; /*!HC:TinArr*/ double * tmpIn = pInArr; if (createIndices) { /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { leadEnd = tmpIn + leadDimLen * inc; #region HYCALPER PRELOOP result = /*!HC:LIMITS*/ double.MinValue; #endregion HYCALPER PRELOOP while (tmpIn < leadEnd) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(leadDimLen - (leadEnd - tmpIn) / inc); } tmpIn += inc; } #region HYCALPER POSTLOOP *(tmpOut) = (/*!HC:ToutArr*/ double ) result; #endregion HYCALPER POSTLOOP tmpOut += inc; tmpInd += inc; if (tmpOut > lastElementOut) { tmpOut -= outLength; tmpInd -= outLength; } if (tmpIn > lastElementIn) tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } else { for (int h = nrHigherDims; h-- > 0; ) { leadEnd = tmpIn + leadDimLen * inc; #region HYCALPER PRELOOP result = /*!HC:LIMITS*/ double.MinValue; #endregion HYCALPER PRELOOP while (tmpIn < leadEnd) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } tmpIn += inc; } #region HYCALPER POSTLOOP *(tmpOut) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut -= outLength; } if (tmpIn > lastElementIn) tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } if (createIndices) { I = new /*!HC:TindCls*/ ILArray<double> (indices, newDims); } return new /*!HC:ToutCls*/ ILArray<double> (retSystemArr, newDims); }
/// <summary> /// maximum along specified dimension /// </summary> /// <param name="A">n-dimensional input array</param> /// <param name="I">return value. If this is an instance of an ILArray /// (f.e. 'empty'), on return I will hold the indices into leadDim of /// the values found. If, on entering the function, I is null, those indices /// will not be computed and I will be ignored.</param> /// <param name="leadDim">index of dimension to operate along</param> /// <returns>ILArray of same type and size as A, except for dimension /// 'leadDim' which will be reduced to 1.</returns> public static /*!HC:ToutCls*/ ILArray<double> /*!HC:funcname*/ max (/*!HC:TinCls*/ ILArray<double> A, ref /*!HC:TindCls*/ ILArray<double> I, int leadDim) { if (A.IsEmpty) { if (!object.Equals (I,null)) I = /*!HC:TindCls*/ ILArray<double> .empty(0,0); return /*!HC:ToutCls*/ ILArray<double> .empty(A.Dimensions); } if (A.IsScalar) { if (!object.Equals(I,null)) I = /*!HC:TindCls*/ ILArray<double> .zeros(1,1); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); if (leadDim >= newDims.Length || inDim[leadDim] == 1) // scalar or sum over singleton -> return copy return new /*!HC:ToutCls*/ ILArray<double> (A); int newLength; newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; /*!HC:ToutArr*/ double [] retSystemArr; retSystemArr = ILMemoryPool.Pool.New</*!HC:ToutArr*/ double >(newLength); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; #region HYCALPER GLOBAL_INIT /*!HC:TinArr*/ double result; /*!HC:TinArr*/ double curval; /*!HC:TindArr*/ double [] indices = null; bool createIndices = false; if (!Object.Equals(I,null)) { indices = new /*!HC:TindArr*/ double [retSystemArr.Length]; createIndices = true; } #endregion HYCALPER GLOBAL_INIT #region HYCALPER INIT_COMPLEX #endregion HYCALPER INIT_COMPLEX if (A.IsReference) { #region Reference storage // ======================== REFERENCE double Storage =========== if (A.IsMatrix) { #region Matrix //////////////////////////// MATRIX /////////////////////// unsafe { ILIndexOffset idxOffset = A.m_indexOffset; int secDim = (leadDim + 1) % 2; fixed (int* leadDimStart = idxOffset[leadDim], secDimStart = idxOffset[secDim]) { fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:ToutArr*/ double * tmpOut = pOutArr; /*!HC:TindArr*/ double * tmpInd = pIndices; /*!HC:ToutArr*/ double * lastElementOut = tmpOut + retSystemArr.Length; /*!HC:TinArr*/ double * tmpIn = pInArr; int* secDimEnd = secDimStart + idxOffset[secDim].Length - 1; int* secDimIdx = secDimStart; int* leadDimIdx = leadDimStart; int* leadDimEnd = leadDimStart + leadDimLen - 1; // start at first element if (createIndices) { while (secDimIdx <= secDimEnd) { tmpIn = pInArr + *secDimIdx++; leadDimIdx = leadDimStart; result = *(tmpIn + *leadDimIdx); #region HYCALPER PRELOOP #1 while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double.IsNaN(result) && ++leadDimIdx <= leadDimEnd ) { result = *(tmpIn + *leadDimIdx); *tmpInd = (/*!HC:TindArr*/ double )(leadDimIdx - leadDimStart); } #endregion HYCALPER PRELOOP #1 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (leadDimIdx <= leadDimEnd) { curval = (*(tmpIn + *leadDimIdx)); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(leadDimIdx - leadDimStart); } leadDimIdx ++; } #region HYCALPER POSTLOOP *(tmpOut++) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP tmpInd++; } } else { while (secDimIdx <= secDimEnd) { tmpIn = pInArr + *secDimIdx++; leadDimIdx = leadDimStart; #region HYCALPER PRELOOP #2 result = *(tmpIn + *leadDimIdx); while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double.IsNaN(result) && ++leadDimIdx <= leadDimEnd ) { result = *(tmpIn + *leadDimIdx); } #endregion HYCALPER PRELOOP #2 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (leadDimIdx <= leadDimEnd) { curval = *(tmpIn + *leadDimIdx++); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } } #region HYCALPER POSTLOOP *(tmpOut++) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP } } } } } #endregion } else if (A.IsVector) { #region Vector //////////////////////////// VECTOR /////////////////////// unsafe { ILIndexOffset idxOffset = A.m_indexOffset; int[] curPosition = new int[2]; int secDim = (leadDim + 1) % 2; fixed (int* leadDimStart = idxOffset[leadDim]) fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) { /*!HC:ToutArr*/ double * tmpOut = pOutArr; /*!HC:TinArr*/ double * tmpIn = pInArr; int* leadDimIdx = leadDimStart; int* leadDimEnd = leadDimStart + leadDimLen; #region HYCALPER PRELOOP #3 result = *(tmpIn + *leadDimIdx); while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && ++leadDimIdx <= leadDimEnd ) { result = *(tmpIn + *leadDimIdx); indices[0] += 1; } #endregion HYCALPER PRELOOP #3 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT // start at first element if (createIndices) { while (leadDimIdx < leadDimEnd) { curval = *(tmpIn + *leadDimIdx); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP indices[0] = leadDimIdx - leadDimStart; } leadDimIdx++; } } else { while (leadDimIdx < leadDimEnd) { curval = *(tmpIn + *leadDimIdx++); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } } #region HYCALPER POSTLOOP *tmpOut = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP } } } #endregion } else { ///////////////////////////// ARBITRARY DIMENSIONS ////////// #region arbitrary size unsafe { ILIndexOffset idxOffset = A.m_indexOffset; int[] curPosition = new int[A.Dimensions.NumberOfDimensions]; fixed (int* leadDimStart = idxOffset[leadDim]) fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:ToutArr*/ double * tmpOut = pOutArr; /*!HC:ToutArr*/ double * lastElementOut = tmpOut + retSystemArr.Length - 1; /*!HC:TinArr*/ double * tmpIn = pInArr; /*!HC:TindArr*/ double * tmpInd = pIndices; int* leadDimIdx = leadDimStart; int* leadDimEnd = leadDimStart + leadDimLen; int inc = inDim.SequentialIndexDistance(leadDim); int dimLen = curPosition.Length; int d, curD; int outLength = newLength - 1; int outCount = 0; // start at first element if (createIndices) { while (outCount < retSystemArr.Length) { leadDimIdx = leadDimStart; #region HYCALPER PRELOOP #4 result = *(tmpIn + *leadDimIdx); while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && ++leadDimIdx <= leadDimEnd ) { result = *(tmpIn + *leadDimIdx); *tmpInd += 1; } #endregion HYCALPER PRELOOP #4 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (leadDimIdx < leadDimEnd) { curval = *(tmpIn + *leadDimIdx); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(leadDimIdx - leadDimStart); } leadDimIdx++; } #region HYCALPER POSTLOOP *tmpOut = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP tmpOut += inc; tmpInd += inc; if (tmpOut > lastElementOut) { tmpOut -= outLength; tmpInd -= outLength; } outCount++; // increment higher dimensions d = 1; while (d < dimLen) { curD = (d + leadDim) % dimLen; tmpIn -= idxOffset[curD, curPosition[curD]]; curPosition[curD]++; if (curPosition[curD] < idxOffset[curD].Length) { tmpIn += idxOffset[curD, curPosition[curD]]; break; } curPosition[curD] = 0; tmpIn += idxOffset[curD, curPosition[curD]]; d++; } } } else { // no indices while (outCount < retSystemArr.Length) { leadDimIdx = leadDimStart; #region HYCALPER PRELOOP #5 result = *(tmpIn + *leadDimIdx); while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && ++leadDimIdx <= leadDimEnd ) { result = *(tmpIn + *leadDimIdx); } #endregion HYCALPER PRELOOP #5 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (leadDimIdx < leadDimEnd) { curval = *(tmpIn + *leadDimIdx++); #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } } #region HYCALPER POSTLOOP *tmpOut = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP tmpOut += inc; if (tmpOut > lastElementOut) tmpOut -= outLength; outCount++; // increment higher dimensions d = 1; while (d < dimLen) { curD = (d + leadDim) % dimLen; tmpIn -= idxOffset[curD, curPosition[curD]]; curPosition[curD]++; if (curPosition[curD] < idxOffset[curD].Length) { tmpIn += idxOffset[curD, curPosition[curD]]; break; } curPosition[curD] = 0; tmpIn += idxOffset[curD, curPosition[curD]]; d++; } } } } } #endregion } #endregion } else { // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:TinArr*/ double * lastElement; /*!HC:ToutArr*/ double * tmpOut = pOutArr; /*!HC:TinArr*/ double * tmpIn = pInArr; if (createIndices) { /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; #region HYCALPER PRELOOP #6 result = *tmpIn; while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && ++tmpIn < lastElement ) { result = *tmpIn; *tmpInd += 1; } #endregion HYCALPER PRELOOP #6 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (tmpIn < lastElement) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(tmpIn - (lastElement - leadDimLen)); } tmpIn++; } *(tmpOut++) = (/*!HC:ToutArr*/ double )result; tmpInd++; } } else { // no indices /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; #region HYCALPER PRELOOP #7 result = *tmpIn; while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && ++tmpIn < lastElement ) { result = *tmpIn; } #endregion HYCALPER PRELOOP #7 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (tmpIn < lastElement) { curval = *tmpIn++; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } } #region HYCALPER POSTLOOP *(tmpOut++) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP } } } } #endregion physical along 1st leading dimension } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed (/*!HC:ToutArr*/ double * pOutArr = retSystemArr) fixed (/*!HC:TinArr*/ double * pInArr = A.m_data) fixed (/*!HC:TindArr*/ double * pIndices = indices) { /*!HC:ToutArr*/ double * lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements -1; /*!HC:TinArr*/ double * lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); /*!HC:ToutArr*/ double * tmpOut = pOutArr; int outLength = newLength - 1; /*!HC:TinArr*/ double * leadEnd; /*!HC:TinArr*/ double * tmpIn = pInArr; if (createIndices) { /*!HC:TindArr*/ double * tmpInd = pIndices; for (int h = nrHigherDims; h-- > 0; ) { leadEnd = tmpIn + leadDimLen * inc; #region HYCALPER PRELOOP #8 result = *tmpIn; while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double.IsNaN(result) && (tmpIn += inc) < leadEnd ) { result = *tmpIn; *tmpInd += 1; } #endregion HYCALPER PRELOOP #8 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (tmpIn < leadEnd) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP *tmpInd = (/*!HC:TindArr*/ double )(leadDimLen - (leadEnd - tmpIn) / inc); } tmpIn += inc; } #region HYCALPER POSTLOOP *(tmpOut) = (/*!HC:ToutArr*/ double ) result; #endregion HYCALPER POSTLOOP tmpOut += inc; tmpInd += inc; if (tmpOut > lastElementOut) { tmpOut -= outLength; tmpInd -= outLength; } if (tmpIn > lastElementIn) tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } else { // no indices for (int h = nrHigherDims; h-- > 0; ) { leadEnd = tmpIn + leadDimLen * inc; #region HYCALPER PRELOOP #9 result = *tmpIn; while ( /*!HC:checkResultStart*/ /*!HC:TinArr*/ double .IsNaN(result) && (tmpIn += inc) < leadEnd ) { result = *tmpIn; } #endregion HYCALPER PRELOOP #9 #region HYCALPER TAKERESULT #endregion HYCALPER TAKERESULT while (tmpIn < leadEnd) { curval = *tmpIn; #region HYCALPER INNERLOOP if (curval > result) { result = curval; #endregion HYCALPER INNERLOOP } tmpIn += inc; } #region HYCALPER POSTLOOP *(tmpOut) = (/*!HC:ToutArr*/ double )result; #endregion HYCALPER POSTLOOP tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut -= outLength; } if (tmpIn > lastElementIn) tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } } if (createIndices) { I = new /*!HC:TindCls*/ ILArray<double> (indices, newDims); } return new /*!HC:ToutCls*/ ILArray<double> (retSystemArr, newDims); }