/// <summary> /// Applys the function (delegate) given to all elements of the storage /// </summary> /// <param name="inArray">storage array to apply the function to</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns>new <![CDATA[ ILArray<complex> ]]> with result of operation</returns> /// <remarks> the values of inArray will not be altered.</remarks> private static ILArray <complex> ComplexOperatorComplex(ILArray <complex> inArray, ILComplexFunctionComplex operation) { ILDimension inDim = inArray.Dimensions; complex [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; retDblArr = new complex [newLength]; int leadDimLen = inDim [0]; unsafe { fixed(complex *pOutArr = retDblArr) fixed(complex * pInArr = inArray.m_data) { complex *lastElement = pOutArr + retDblArr.Length; complex *tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) { *tmpOut++ = operation(*tmpIn++); } } } return(new ILArray <complex> (retDblArr, inDim.ToIntArray())); }
/// <summary> /// Applys the function (delegate) given to all elements of the storage /// </summary> /// <param name="inArray">storage array to apply the function to</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns>new <![CDATA[ ILArray<byte> ]]> with result of operation</returns> /// <remarks> the values of inArray will not be altered.</remarks> private static ILArray <byte> ByteOperatorByte(ILArray <byte> inArray, ILByteFunctionByte operation) { ILDimension inDim = inArray.Dimensions; byte [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; retDblArr = new byte [newLength]; int leadDimLen = inDim [0]; unsafe { fixed(byte *pOutArr = retDblArr) fixed(byte *pInArr = inArray.m_data) { byte *lastElement = pOutArr + retDblArr.Length; byte *tmpOut = pOutArr; byte *tmpIn = pInArr; while (tmpOut < lastElement) { *tmpOut++ = operation(*tmpIn++); } } } return(new ILArray <byte> (retDblArr, inDim.ToIntArray())); }
/*!HC:TYPELIST: * <hycalper> * <type> * <source locate="after"> * inArr1 * </source> * <destination>byte</destination> * <destination>complex</destination> * <destination>complex</destination> * <destination>double</destination> * </type> * <type> * <source locate="after"> * inCls1 * </source> * <destination><![CDATA[ILArray<byte>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * <destination><![CDATA[ILArray<double>]]></destination> * </type> * <type> * <source locate="after"> * outCls1 * </source> * <destination><![CDATA[ILArray<byte>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * <destination><![CDATA[ILArray<double>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * </type> * <type> * <source locate="after"> * outArr1 * </source> * <destination>byte</destination> * <destination>complex</destination> * <destination>double</destination> * <destination>complex</destination> * </type> * <type> * <source locate="after"> * delegate_unary * </source> * <destination>ILByteFunctionByte</destination> * <destination>ILComplexFunctionComplex</destination> * <destination>ILDoubleFunctionComplex</destination> * <destination>ILComplexFunctionDouble</destination> * </type> * <type> * <source locate="after"> * unaryop * </source> * <destination>ByteOperatorByte</destination> * <destination>ComplexOperatorComplex</destination> * <destination>DoubleOperatorComplex</destination> * <destination>ComplexOperatorDouble</destination> * </type> * </hycalper> */ /// <summary> /// Applys the function (delegate) given to all elements of the storage /// </summary> /// <param name="inArray">storage array to apply the function to</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns>new <![CDATA[ /*!HC:outCls1*/ ILArray<double> ]]> with result of operation</returns> /// <remarks> the values of inArray will not be altered.</remarks> private static /*!HC:outCls1*/ ILArray <double> /*!HC:unaryop*/ DoubleOperatorDouble(/*!HC:inCls1*/ ILArray <double> inArray, /*!HC:delegate_unary*/ ILDoubleFunctionDouble operation) { ILDimension inDim = inArray.Dimensions; /*!HC:outArr1*/ double [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; retDblArr = new /*!HC:outArr1*/ double [newLength]; int leadDimLen = inDim [0]; unsafe { fixed(/*!HC:outArr1*/ double *pOutArr = retDblArr) fixed(/*!HC:inArr1*/ double *pInArr = inArray.m_data) { /*!HC:outArr1*/ double *lastElement = pOutArr + retDblArr.Length; /*!HC:outArr1*/ double *tmpOut = pOutArr; /*!HC:inArr1*/ double * tmpIn = pInArr; while (tmpOut < lastElement) { *tmpOut++ = operation(*tmpIn++); } } } return(new /*!HC:outCls1*/ ILArray <double> (retDblArr, inDim.ToIntArray())); }
/// <summary> /// operate on elements of both storages by the given function -> relational operations /// </summary> /// <param name="inArray1">First storage array</param> /// <param name="inArray2">Second storage array</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns><![CDATA[ ILArray<byte> ]]> with result of operation for corresponding /// elements of both arrays.</returns> /// <remarks>The values of inArray1 nor inArray2 will not be altered.The dimensions /// of both arrays must match.</remarks> private static ILArray <byte> ByteOperatorByteByte(ILArray <byte> inArray1, ILArray <byte> inArray2, ILByteFunctionByteByte operation) { ILDimension inDim = inArray1.Dimensions; if (!inDim.IsSameSize(inArray2.Dimensions)) { throw new ILDimensionMismatchException(); } byte [] retSystemArr; // build ILDimension int newLength = inDim.NumberOfElements; retSystemArr = new byte [newLength]; int leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(byte *pInArr1 = inArray1.m_data) fixed(byte *pInArr2 = inArray2.m_data) fixed(byte *pOutArr = retSystemArr) { byte *poutarr = pOutArr; byte *poutend = poutarr + newLength; byte *pIn1 = pInArr1; byte *pIn2 = pInArr2; while (poutarr < poutend) { *poutarr++ = operation(*pIn1++, *pIn2++); } } } return(new ILArray <byte> (retSystemArr, inDim.ToIntArray())); }
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <summary> /// operate on elements of both storages by the given function -> relational operations /// </summary> /// <param name="inArray1">First storage array</param> /// <param name="inArray2">Second storage array</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns><![CDATA[ ILArray<complex> ]]> with result of operation for corresponding /// elements of both arrays.</returns> /// <remarks>The values of inArray1 nor inArray2 will not be altered.The dimensions /// of both arrays must match.</remarks> private static ILArray <complex> ComplexOperatorComplexComplex(ILArray <complex> inArray1, ILArray <complex> inArray2, ILComplexFunctionComplexComplex operation) { ILDimension inDim = inArray1.Dimensions; if (!inDim.IsSameSize(inArray2.Dimensions)) { throw new ILDimensionMismatchException(); } complex [] retSystemArr; // build ILDimension int newLength = inDim.NumberOfElements; retSystemArr = new complex [newLength]; int leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(complex *pInArr1 = inArray1.m_data) fixed(complex * pInArr2 = inArray2.m_data) fixed(complex * pOutArr = retSystemArr) { complex *poutarr = pOutArr; complex *poutend = poutarr + newLength; complex *pIn1 = pInArr1; complex *pIn2 = pInArr2; while (poutarr < poutend) { *poutarr++ = operation(*pIn1++, *pIn2++); } } } return(new ILArray <complex> (retSystemArr, inDim.ToIntArray())); }
/*!HC:TYPELIST: * <hycalper> * <type> * <source locate="after"> * inArr1 * </source> * <destination>byte</destination> * <destination>complex</destination> * </type> * <type> * <source locate="after"> * inArr2 * </source> * <destination>byte</destination> * <destination>complex</destination> * </type> * <type> * <source locate="after"> * inCls1 * </source> * <destination><![CDATA[ILArray<byte>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * </type> * <type> * <source locate="after"> * inCls2 * </source> * <destination><![CDATA[ILArray<byte>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * </type> * <type> * <source locate="after"> * outCls1 * </source> * <destination><![CDATA[ILArray<byte>]]></destination> * <destination><![CDATA[ILArray<complex>]]></destination> * </type> * <type> * <source locate="after"> * outArr1 * </source> * <destination>byte</destination> * <destination>complex</destination> * </type> * <type> * <source locate="after"> * delegate_binary * </source> * <destination>ILByteFunctionByteByte</destination> * <destination>ILComplexFunctionComplexComplex</destination> * </type> * <type> * <source locate="after"> * hcfunctionName * </source> * <destination>ByteOperatorByteByte</destination> * <destination>ComplexOperatorComplexComplex</destination> * </type> * </hycalper> */ /// <summary> /// operate on elements of both storages by the given function -> relational operations /// </summary> /// <param name="inArray1">First storage array</param> /// <param name="inArray2">Second storage array</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns><![CDATA[ /*!HC:outCls1*/ ILArray<double> ]]> with result of operation for corresponding /// elements of both arrays.</returns> /// <remarks>The values of inArray1 nor inArray2 will not be altered.The dimensions /// of both arrays must match.</remarks> private static /*!HC:outCls1*/ ILArray <double> /*!HC:hcfunctionName*/ DoubleOperatorDoubleDouble(/*!HC:inCls1*/ ILArray <double> inArray1, /*!HC:inCls2*/ ILArray <double> inArray2, /*!HC:delegate_binary*/ ILDoubleFunctionDoubleDouble operation) { ILDimension inDim = inArray1.Dimensions; if (!inDim.IsSameSize(inArray2.Dimensions)) { throw new ILDimensionMismatchException(); } /*!HC:outArr1*/ double [] retSystemArr; // build ILDimension int newLength = inDim.NumberOfElements; retSystemArr = new /*!HC:outArr1*/ double [newLength]; int leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(/*!HC:inArr1*/ double *pInArr1 = inArray1.m_data) fixed(/*!HC:inArr2*/ double *pInArr2 = inArray2.m_data) fixed(/*!HC:outArr1*/ double *pOutArr = retSystemArr) { /*!HC:outArr1*/ double *poutarr = pOutArr; /*!HC:outArr1*/ double *poutend = poutarr + newLength; /*!HC:inArr1*/ double * pIn1 = pInArr1; /*!HC:inArr2*/ double * pIn2 = pInArr2; while (poutarr < poutend) { *poutarr++ = operation(*pIn1++, *pIn2++); } } } return(new /*!HC:outCls1*/ ILArray <double> (retSystemArr, inDim.ToIntArray())); }
/// <summary> /// Applys the function (delegate) given to all elements of the storage /// </summary> /// <param name="inArray">storage array to be apply the function to</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns>new ILArray<double> with result</returns> /// <remarks> the values of inArray will not be altered.</remarks> private static ILLogicalArray LogicalUnaryDoubleOperator(ILArray <double> inArray, ILApplyLogical_Double operation) { ILDimension inDim = inArray.Dimensions; byte[] retByteArr; // build ILDimension int newLength = inDim.NumberOfElements; retByteArr = new byte[newLength]; int leadDim = 0; int leadDimLen = inDim[0]; if (inArray.IsReference) { #region Reference storage // walk along the longest dimension (for performance reasons) for (int i = 1; i < inDim.NumberOfDimensions; i++) { if (leadDimLen < inDim[i]) { leadDimLen = inDim[i]; leadDim = i; } } ILIndexOffset idxOffset = inArray.m_indexOffset; int incOut = inDim.SequentialIndexDistance(leadDim); // ======================== REFERENCE double Storage =========== if (inArray.IsMatrix) { #region Matrix //////////////////////////// MATRIX //////////////////// int secDim = (leadDim + 1) % 2; unsafe { fixed(int *leadDimStart = idxOffset[leadDim], secDimStart = idxOffset[secDim]) { fixed(byte *pOutArr = retByteArr) { fixed(double *pInArr = inArray.m_data) { byte * tmpOut = pOutArr; double *tmpIn = pInArr; byte * tmpOutEnd = pOutArr + inDim.NumberOfElements - 1; int * secDimEnd = secDimStart + idxOffset[secDim].Length; int * secDimIdx = secDimStart; int * leadDimIdx = leadDimStart; int * leadDimEnd = leadDimStart + idxOffset[secDim].Length;; while (secDimIdx < secDimEnd) { tmpIn = pInArr + *secDimIdx++; leadDimIdx = leadDimStart; while (leadDimIdx < leadDimEnd) { *tmpOut = operation(*(tmpIn + *leadDimIdx++)); tmpOut += incOut; } if (tmpOut > tmpOutEnd) { tmpOut = pOutArr + (tmpOutEnd - tmpOut); } } } } } } #endregion } else if (inArray.IsVector) { #region Vector //////////////////////////// VECTOR /////////////////////// unsafe { fixed(int *leadDimStart = idxOffset[leadDim]) { fixed(byte *pOutArr = retByteArr) { fixed(double *pInArr = inArray.m_data) { byte * tmpOut = pOutArr; double *tmpIn = pInArr + idxOffset[((leadDim + 1) % 2), 0]; int * leadDimIdx = leadDimStart; int * leadDimEnd = leadDimStart + leadDimLen; // start at first element while (leadDimIdx < leadDimEnd) { *tmpOut++ = operation(*(tmpIn + *leadDimIdx++)); } } } } } #endregion } else { ///////////////////////////// ARBITRARY DIMENSIONS ////////// #region arbitrary size unsafe { int[] curPosition = new int[inArray.Dimensions.NumberOfDimensions]; fixed(int *leadDimStart = idxOffset[leadDim]) { fixed(byte *pOutArr = retByteArr) { fixed(double *pInArr = inArray.m_data) { byte *tmpOut = pOutArr; byte *tmpOutEnd = tmpOut + retByteArr.Length; // init lesezeiger: add alle Dimensionen mit 0 (außer leadDim) double *tmpIn = pInArr + inArray.getBaseIndex(0, 0); tmpIn -= idxOffset[leadDim, 0]; int *leadDimIdx = leadDimStart; int *leadDimEnd = leadDimStart + leadDimLen; int dimLen = curPosition.Length; int d, curD; // start at first element while (tmpOut < tmpOutEnd) { leadDimIdx = leadDimStart; while (leadDimIdx < leadDimEnd) { *tmpOut = operation(*(tmpIn + *leadDimIdx++)); tmpOut += incOut; } if (tmpOut > tmpOutEnd) { tmpOut = pOutArr + (tmpOutEnd - tmpOut); } // 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, 0]; d++; } } } } } } #endregion } // ============================================================== #endregion } else { // physical -> pointer arithmetic #region physical storage unsafe { fixed(byte *pOutArr = retByteArr) { fixed(double *pInArr = inArray.m_data) { byte * lastElement = pOutArr + retByteArr.Length; byte * tmpOut = pOutArr; double *tmpIn = pInArr; while (tmpOut < lastElement) { *tmpOut++ = operation(*tmpIn++); } } } } #endregion } return(new ILLogicalArray(retByteArr, inDim.ToIntArray())); }
/// <summary> /// operate on elements of both storages by the given function -> relational operations /// </summary> /// <param name="inArray1">First storage array</param> /// <param name="inArray2">Second storage array</param> /// <param name="operation">operation to apply to the elements of inArray. This /// acts like a function pointer.</param> /// <returns>new ILLogicalArray with result of operation for corresponding /// elements of both arrays.</returns> /// <remarks>The values of inArray2 nor inArray2 will not be altered.The dimensions /// of both arrays must match.</remarks> private static ILArray <double> DoubleBinaryDoubleOperator(ILArray <double> inArray1, ILArray <double> inArray2, ILApplyDouble_DoubleDouble operation) { ILDimension inDim = inArray1.Dimensions; if (!inDim.IsSameSize(inArray2.Dimensions)) { throw new Exception("Array dimensions must match."); } double[] retBoolArr; // build ILDimension int newLength = inDim.NumberOfElements; retBoolArr = new double[newLength]; int leadDim = 0; int leadDimLen = inDim[0]; if (inArray1.IsReference || inArray2.IsReference) { // this will most probably be not very fast, but .... :| #region Reference storage // walk along the longest dimension (for performance reasons) for (int i = 1; i < inDim.NumberOfDimensions; i++) { if (leadDimLen < inDim[i]) { leadDimLen = inDim[i]; leadDim = i; } } ILIterator <double> it1 = inArray1.CreateIterator(ILIteratorPositions.ILEnd, leadDim); ILIterator <double> it2 = inArray2.CreateIterator(ILIteratorPositions.ILEnd, leadDim); unsafe { fixed(double *pOutArr = retBoolArr) { double *poutarr = pOutArr; double *outEnd = poutarr + newLength; while (poutarr < outEnd) { *poutarr++ = operation(it1.Increment(), it2.Increment()); } } } // ============================================================== #endregion } else { // physical -> pointer arithmetic #region physical storage unsafe { fixed(double *pInArr1 = inArray1.m_data, pInArr2 = inArray2.m_data) { fixed(double *pOutArr = retBoolArr) { double *poutarr = pOutArr; double *poutend = poutarr + newLength; double *pIn1 = pInArr1; double *pIn2 = pInArr2; while (poutarr < poutend) { *poutarr++ = operation(*pIn1++, *pIn2++); } } } } #endregion } return(new ILArray <double>(retBoolArr, inDim.ToIntArray())); }
/// <summary> /// First derivative along specific dimension /// </summary> /// <param name="A">input array</param> /// <param name="leadDim">dimensions to create derivative along</param> /// <returns>array with first derivative of A along dimension <code>lieadDim</code></returns> private static ILArray <complex> diff(int leadDim, ILArray <complex> A) { if (A.IsEmpty) { return(ILArray <complex> .empty(A.Dimensions)); } if (A.IsScalar) { return(ILArray <complex> .empty(0, 0)); } if (leadDim < 0) { throw new ILArgumentException("dimension parameter out of range!"); } if (leadDim >= A.Dimensions.NumberOfDimensions) { int[] outDims = A.Dimensions.ToIntArray(leadDim + 1); outDims[leadDim] = 0; return(ILArray <complex> .empty(outDims)); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); if (inDim[leadDim] == 1) { return(ILArray <complex> .empty(0, 0)); } int newLength; complex [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim]--; newLength = newLength * newDims[leadDim]; retDblArr = ILMemoryPool.Pool.New <complex>(newLength); ILDimension newDimension = new ILDimension(newDims); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; int incOut = newDimension.SequentialIndexDistance(leadDim); complex firstVal, secVal; if (A.IsVector) { return(A["1:end"] - A[vector(0, A.Length - 2)]); } // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed(complex *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { complex *lastElement; complex *tmpOut = pOutArr; complex *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { lastElement = tmpIn + leadDimLen; firstVal = *tmpIn++; while (tmpIn < lastElement) { secVal = *tmpIn++; *(tmpOut++) = ( complex )(secVal - firstVal); firstVal = secVal; } } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed(complex *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { complex *lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements - 1; complex *lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); complex *tmpOut = pOutArr; int outLength = newLength - 1; complex *leadEnd; complex *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { leadEnd = tmpIn + leadDimLen * inc; firstVal = *tmpIn; tmpIn += inc; while (tmpIn < leadEnd) { secVal = *tmpIn; *tmpOut = ( complex )(secVal - firstVal); tmpIn += inc; tmpOut += incOut; firstVal = secVal; } if (tmpOut > lastElementOut) { tmpOut -= outLength; } if (tmpIn > lastElementIn) { tmpIn -= inLength; } } } } #endregion } return(new ILArray <complex> (retDblArr, newDimension));; }
/// <summary> /// Multiply elements of inArray along specified dimension. /// </summary> /// <param name="inArray">N-dimensional double array</param> /// <param name="leadDim">index of dimension to multiply elements along</param> /// <returns>array having the 'leadDim's dimension /// reduced to the length of 1 with the result of the product of /// corresponding elements of inArray of that dimension.</returns> public static ILArray <double> prod(ILArray <double> inArray, int leadDim) { ILDimension inDim = inArray.Dimensions; int[] newDims = inDim.ToIntArray(); if (leadDim == newDims.Length || inDim[leadDim] == 1) { // scalar or sum over singleton -> return copy return((ILArray <double>)inArray.Clone()); } int newLength; double[] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New <double>(newLength); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *lastElement; double *tmpOut = pOutArr; double *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { lastElement = tmpIn + leadDimLen; *tmpOut = 1.0; while (tmpIn < lastElement) { *tmpOut *= *tmpIn++; } tmpOut++; } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements - 1; double *lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); double *tmpOut = pOutArr; int outLength = newLength - 1; double *leadEnd; double *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { leadEnd = tmpIn + leadDimLen * inc; *tmpOut = 1.0; while (tmpIn < leadEnd) { *tmpOut *= *tmpIn; tmpIn += inc; } tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength); } if (tmpIn > lastElementIn) { tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } return(new ILArray <double>(retDblArr, newDims));; }
/// <summary> /// vertical concatenation for arbitrary arrays /// </summary> /// <param name="inArrays"> arrays to be concatenated with each other. All /// arrays must be of the same inner type. The dimensions of all arrays /// must match - except the first dimension.</param> /// <returns>large array having all arrays in 'inArrays' placed beneath each other. /// </returns> /// <remarks>The array returned may be a reference array if all elements of 'inArrays' /// point to the same object instance, or a solid array otherwise. In the case of /// all elements pointing to the same object, the static member /// ILNumerics.ILSettings.MinimumRefDimensions will be taken into account too. /// /// Vertical concatenation means concatenation along the first dimension. /// </remarks> public static ILArray <T> vertcat <T>(params ILArray <T>[] toCat) { // Input checking int nElementsOut = 0; int nRowsOut = 0; ILDimension aValidDim = null; int[] seqDist = new int[toCat.Length]; int[] posInEachToCat = new int[toCat.Length]; for (int i = 0; i < toCat.Length; i++) { if (!toCat[i].IsEmpty) { nElementsOut += toCat[i].m_dimensions.NumberOfElements; nRowsOut += toCat[i].m_dimensions[0]; seqDist[i] = toCat[i].m_dimensions.SequentialIndexDistance(1); if (aValidDim == null) { aValidDim = toCat[i].m_dimensions; continue; } if (aValidDim.NumberOfDimensions != toCat[i].m_dimensions.NumberOfDimensions) { throw new ILArgumentSizeException("vertcat: Both arrays to be concatenated must have the same number of dimensions!"); } for (int j = 1; j < aValidDim.NumberOfDimensions; j++) { if (aValidDim[j] != toCat[i].m_dimensions[j]) { throw new Exception("vertcat: all but the second dimensions of all arrays must match!"); } } } } if (nElementsOut == 0) { return(new ILArray <T>()); } // Allocate T[] outArray = ILMemoryPool.Pool.New <T>(nElementsOut); // Concat int posInOutArray = 0, posInToCat = 0; while (posInOutArray < nElementsOut) { if (posInToCat >= toCat.Length) { posInToCat = 0; } int thisSeqDist = seqDist[posInToCat]; T[] thisArray = toCat[posInToCat].m_data; for (int i = 0; i < thisSeqDist; i++) { outArray[posInOutArray++] = thisArray[posInEachToCat[posInToCat]++]; } posInToCat++; } int[] retDimArray = aValidDim.ToIntArray(); retDimArray[0] = nRowsOut; return(new ILArray <T>(outArray, new ILDimension(retDimArray))); }
/// <summary> /// Create new ILArray<double>, setting initial element values to one. /// </summary> /// <returns>Physical ILArray<double> with all elements set to one. </returns> public static ILArray <double> ones(ILDimension dimensions) { return(ones(dimensions.ToIntArray())); }
/// <summary> /// Multiply elements of inArray along specified dimension. /// </summary> /// <param name="inArray">N-dimensional double array</param> /// <param name="leadDim">index of dimension to multiply elements along</param> /// <returns>array having the 'leadDim's dimension /// reduced to the length of 1 with the result of the product of /// corresponding elements of inArray of that dimension.</returns> public static ILArray <double> prod(ILArray <double> inArray, int leadDim) { ILDimension inDim = inArray.Dimensions; int[] newDims = inDim.ToIntArray(); if (leadDim == newDims.Length || inDim[leadDim] == 1) { // scalar or sum over singleton -> return copy return((ILArray <double>)inArray.Clone()); } int newLength; double[] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New <double>(newLength); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; if (inArray.IsReference) { #region Reference storage // ======================== REFERENCE double Storage =========== if (inArray.IsMatrix) { #region Matrix //////////////////////////// MATRIX /////////////////////// unsafe { ILIndexOffset idxOffset = inArray.m_indexOffset; int secDim = (leadDim + 1) % 2; fixed(int *leadDimStart = idxOffset[leadDim], secDimStart = idxOffset[secDim]) { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *tmpOut = pOutArr; double *lastElementOut = tmpOut + retDblArr.Length; 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 while (secDimIdx <= secDimEnd) { tmpIn = pInArr + *secDimIdx++; leadDimIdx = leadDimStart; *tmpOut = 1.0; while (leadDimIdx <= leadDimEnd) { *tmpOut *= *(tmpIn + *leadDimIdx++); } tmpOut++; } } } } #endregion } else if (inArray.IsVector) { #region Vector //////////////////////////// VECTOR /////////////////////// unsafe { ILIndexOffset idxOffset = inArray.m_indexOffset; int[] curPosition = new int[2]; int secDim = (leadDim + 1) % 2; fixed(int *leadDimStart = idxOffset[leadDim]) { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *tmpOut = pOutArr; double *tmpIn = pInArr; int * leadDimIdx = leadDimStart; int * leadDimEnd = leadDimStart + leadDimLen; // start at first element *tmpOut = 1.0; while (leadDimIdx < leadDimEnd) { *tmpOut *= *(tmpIn + *leadDimIdx++); } } } } #endregion } else { ///////////////////////////// ARBITRARY DIMENSIONS ////////// #region arbitrary size unsafe { ILIndexOffset idxOffset = inArray.m_indexOffset; int[] curPosition = new int[inArray.Dimensions.NumberOfDimensions]; fixed(int *leadDimStart = idxOffset[leadDim]) { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *tmpOut = pOutArr; double *lastElementOut = tmpOut + retDblArr.Length; double *tmpIn = pInArr; int * leadDimIdx = leadDimStart; int * leadDimEnd = leadDimStart + leadDimLen; int dimLen = curPosition.Length; int d, curD; // start at first element while (tmpOut < lastElementOut) { leadDimIdx = leadDimStart; *tmpOut = 1.0; while (leadDimIdx < leadDimEnd) { *tmpOut *= *(tmpIn + *leadDimIdx++); } tmpOut++; // 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(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *lastElement; double *tmpOut = pOutArr; double *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { lastElement = tmpIn + leadDimLen; *tmpOut = 1.0; while (tmpIn < lastElement) { *tmpOut *= *tmpIn++; } tmpOut++; } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed(double *pOutArr = retDblArr, pInArr = inArray.m_data) { double *lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements - 1; double *lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); double *tmpOut = pOutArr; int outLength = newLength - 1; double *leadEnd; double *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { leadEnd = tmpIn + leadDimLen * inc; *tmpOut = 1.0; while (tmpIn < leadEnd) { *tmpOut *= *tmpIn; tmpIn += inc; } tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength); } if (tmpIn > lastElementIn) { tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } } return(new ILArray <double>(retDblArr, newDims));; }
/// <summary>determine, if any elements are nonzero</summary> /// <param name="A">N-dimensional array</param> /// <param name="leadDim">index of dimension to operate along</param> /// <returns><para>array of same size as A, having the 'leadDim's dimension reduced to 1, if any elements along that dimension are non-zero, '0' else. </para></returns> public static ILLogicalArray any(ILArray <complex> A, int leadDim) { if (A.IsEmpty) { return(ILLogicalArray.empty(A.Dimensions)); } if (A.IsScalar) { return(new ILLogicalArray(new byte [1] { (A.GetValue(0).iszero())?(byte)0:(byte)1 }, 1, 1)); } if (leadDim >= A.Dimensions.NumberOfDimensions) { throw new ILArgumentException("dimension parameter out of range!"); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); int tmpCount = 0; int newLength; byte [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New <byte>(newLength); ILDimension newDimension = new ILDimension(newDims); int incOut = newDimension.SequentialIndexDistance(leadDim); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed(byte *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { complex *lastElement; byte * tmpOut = pOutArr; complex *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { lastElement = tmpIn + leadDimLen; while (tmpIn < lastElement) { tmpCount += ((*tmpIn++).iszero())?0:1; } *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; tmpOut++; } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed(byte *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { byte * lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements - 1; complex *lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); byte * tmpOut = pOutArr; int outLength = newLength - 1; complex *leadEnd; complex *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { leadEnd = tmpIn + leadDimLen * inc; while (tmpIn < leadEnd) { tmpCount += ((*tmpIn).iszero())?0:1; tmpIn += inc; } *tmpOut = (tmpCount == 0)? (byte)0:(byte)1; tmpCount = 0; tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength); } if (tmpIn > lastElementIn) { tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } return(new ILLogicalArray(retDblArr, newDims));; }
/// <summary> /// Sum elements of A along dimension specified. /// </summary> /// <param name="A">N-dimensional array</param> /// <param name="leadDim">index of dimension to operate along</param> /// <returns>array, same size as A, but having the 'leadDim's dimension /// reduced to the length 1 with the sum of all /// elements along that dimension.</returns> public static /*!HC:outCls1*/ ILArray <double> /*!HC:funcname*/ sum(/*!HC:inCls1*/ ILArray <double> A, int leadDim) { if (A.IsEmpty) { return /*!HC:outCls1*/ (ILArray <double> .empty(A.Dimensions)); } if (A.IsScalar) { /*!HC:HCscalarOp*/ return(new /*!HC:outCls1*/ ILArray <double> (new /*!HC:inArr1*/ double [] { A.GetValue(0) }, 1, 1)); } if (leadDim >= A.Dimensions.NumberOfDimensions) { throw new ILArgumentException("dimension parameter out of range!"); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); /*!HC:singletonDimOp*/ if (inDim[leadDim] == 1) { return((/*!HC:outCls1*/ ILArray <double>)A.Clone()); } int newLength; /*!HC:outArr1*/ double [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New </*!HC:outArr1*/ double>(newLength); ILDimension newDimension = new ILDimension(newDims); int incOut = newDimension.SequentialIndexDistance(leadDim); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed(/*!HC:outArr1*/ double *pOutArr = retDblArr) fixed(/*!HC:inArr1*/ double *pInArr = A.m_data) { /*!HC:inArr1*/ double * lastElement; /*!HC:outArr1*/ double *tmpOut = pOutArr; /*!HC:inArr1*/ double * tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { lastElement = tmpIn + leadDimLen; /*!HC:HCzero*/ *tmpOut = 0.0; while (tmpIn < lastElement) { /*!HC:tmpOutStorage*/ *tmpOut += /*!HC:preEvalOp*/ (double)(*tmpIn++) /*!HC:postEvalOp*/; } /*!HC:operationResult*/ /**/ tmpOut++; } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed(/*!HC:outArr1*/ double *pOutArr = retDblArr) fixed(/*!HC:inArr1*/ double *pInArr = A.m_data) { /*!HC:outArr1*/ double *lastElementOut = newLength + pOutArr - 1; int inLength = inDim.NumberOfElements - 1; /*!HC:inArr1*/ double *lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); /*!HC:outArr1*/ double *tmpOut = pOutArr; int outLength = newLength - 1; /*!HC:inArr1*/ double *leadEnd; /*!HC:inArr1*/ double *tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0;) { leadEnd = tmpIn + leadDimLen * inc; /*!HC:HCzero*/ *tmpOut = 0.0; while (tmpIn < leadEnd) { /*!HC:tmpOutStorage*/ *tmpOut += /*!HC:preEvalOp*/ (double)(*tmpIn) /*!HC:postEvalOp*/; tmpIn += inc; } /*!HC:operationResult*/ /**/ tmpOut += inc; if (tmpOut > lastElementOut) { tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength); } if (tmpIn > lastElementIn) { tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } } #endregion } return(new /*!HC:outCls1*/ ILArray <double> (retDblArr, newDims));; }