/// <summary> /// [obsolete] copy constructor /// </summary> /// <param name="newDim">ILDimension object to copy this object from</param> /// <remarks>This function is obsolete and will be removed in a future version. Resona: /// ILDimension objects are immutable and can therefore savely be reused for /// multiple arrays.</remarks> private ILDimension (ILDimension newDim) { m_nrDims = newDim.m_nrDims; m_numberOfElements = newDim.m_numberOfElements; m_dims = new int[m_nrDims]; m_length = newDim.m_length; for (int i = 0; i < m_nrDims; i++) { m_dims[i] = newDim[i]; if (m_length < m_dims[i]) m_length = m_dims[i]; } }
/// <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(params int[] dimensions) { ILDimension dim = new ILDimension(dimensions); double[] data = ILMemoryPool.Pool.New<double>(dim.NumberOfElements); ILArray<double> ret = new ILArray<double>(data, dimensions); return set(ret, 1.0); {/* unsafe { fixed(double* pData = data) { double* ende = pData + data.Length; double* curr = pData; while (curr < ende) *curr++ = 1.0; }*/ } }
/// <summary> /// [obsolete] copy constructor /// </summary> /// <param name="newDim">ILDimension object to copy this object from</param> /// <remarks>This function is obsolete and will be removed in a future version. Resona: /// ILDimension objects are immutable and can therefore savely be reused for /// multiple arrays.</remarks> private ILDimension(ILDimension newDim) { m_nrDims = newDim.m_nrDims; m_numberOfElements = newDim.m_numberOfElements; m_dims = new int[m_nrDims]; m_length = newDim.m_length; for (int i = 0; i < m_nrDims; i++) { m_dims[i] = newDim[i]; if (m_length < m_dims[i]) { m_length = m_dims[i]; } } }
private void Test_Squeeze() { int errorCode = 0; try { ILDimension dim = new ILDimension(0,1,1,2); ILDimension result = dim.Squeeze(); if (result.NonSingletonDimensions != 1) throw new Exception("Squeeze failed"); if (result.NumberOfDimensions != 2) throw new Exception("Squeeze failed"); if (result[0] != 0) throw new Exception("Squeeze failed"); if (result[1] != 2) throw new Exception("Squeeze failed"); dim = new ILDimension(1,0,2,1); result = dim.Squeeze(); if (result.NumberOfDimensions != 2) throw new Exception("Squeeze failed"); if (result[0] != 0) throw new Exception("Squeeze failed"); if (result[1] != 2) throw new Exception("Squeeze failed"); dim = new ILDimension(2,1,2,1,2,3,3,1); result = dim.Squeeze(); if (result.NumberOfDimensions != 5) throw new Exception("Squeeze failed"); if (result[0] != 2) throw new Exception("Squeeze failed"); if (result[1] != 2) throw new Exception("Squeeze failed"); if (result[2] != 2) throw new Exception("Squeeze failed"); if (result[3] != 3) throw new Exception("Squeeze failed"); if (result[4] != 3) throw new Exception("Squeeze failed"); dim = new ILDimension(0); result = dim.Squeeze(); if (result.NumberOfDimensions != 2) throw new Exception("Squeeze failed"); if (result[0] != 0) throw new Exception("Squeeze failed"); if (result[1] != 1) throw new Exception("Squeeze failed"); Success(); } catch (Exception e) { Error(errorCode ,e.Message); } }
/// <summary> /// Create array initialized with all elements set to zero. /// </summary> /// <param name="dimensions">Dimension specification.</param> /// <returns>Zeros-filled array.</returns> /// <remarks>The memory for the array is reclaimed from the memory pool, if possible.</remarks> public static ILArray<double> zeros(params int[] dimensions) { ILDimension retDims = new ILDimension(dimensions); bool cleared = false; double[] retArr = ILMemoryPool.Pool.New<double>(retDims.NumberOfElements,false,out cleared); if (!cleared) { unsafe { fixed (double * pRetArr = retArr) { double * walk = pRetArr; double * end = pRetArr + retArr.Length; while (walk < end) *(walk++) = 0.0; } } } return new ILArray<double>(retArr,retDims); }
/// <summary> /// Compares the shape of this dimension to another dimension object /// </summary> /// <param name="dim2">ILDimension object to compare this to.</param> /// <returns>Returns true if the shapes are the same, else returns false. </returns> /// <remarks>This function is more strict than IsSameSize. In order /// for two dimensions to have the same shape, ALL dimensions must match - /// even singleton dimensions.</remarks> public bool IsSameShape(ILDimension dim2) { if (dim2.NumberOfElements != m_numberOfElements) { return(false); } if (dim2.NumberOfDimensions != m_nrDims) { return(false); } for (int d1 = m_nrDims; d1-- > 0;) { if (m_dims[d1] != dim2.m_dims[d1]) { return(false); } } return(true); }
public static ILArray<double> Zeros(params int[] dimensions) { ILDimension dim = new ILDimension(dimensions); double[] data = new double[dim.NumberOfElements]; return new ILArray<double>(data, dimensions); }
/// <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 ILArray<complex> sum ( ILArray<complex> A, int leadDim) { if (A.IsEmpty) return ILArray<complex> .empty(A.Dimensions); if (A.IsScalar) return new ILArray<complex> (new complex []{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(); if (inDim[leadDim] == 1) return ( ILArray<complex> )A.Clone(); int newLength; complex [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New< complex >(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 ( 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; *tmpOut = 0.0; while (tmpIn < lastElement) { *tmpOut += (complex) (*tmpIn++) ; } /**/ tmpOut++; } } } #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; *tmpOut = 0.0; while (tmpIn < leadEnd) { *tmpOut += (complex) (*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<complex> (retDblArr, newDims);; }
/// <summary> /// Create N-dimensional array with elements counting from 1 and specified interval. /// </summary> /// <param name="start">Initial value.</param> /// <param name="increment">Increment for each element.</param> /// <param name="dimensions">Variable int array with dimension specification.</param> /// <returns>Array with elements counting from 1 ... dimensions.NumberOfElements.</returns> /// <remarks><para>Counter is a fast alternative to the creation of arrays via <see cref="ILNumerics.BuiltInFunctions.ILMath.ones(int[])"/> /// or <see cref="ILNumerics.BuiltInFunctions.ILMath.zeros(int[])"/> with subsequent modification. /// Counter is more general. It can create arrays of all constants (zeros, ones, twos ...) if <paramref name="increment"/> is 0, regularly /// incrementing elements if <paramref name="increment"/> is positive or negative.</para> /// This function may also be used for the convenient creation of arrays for testing purposes. /// <para>Keep in mind: in order to distingush this function from the overloaded version <see cref="ILNumerics.BuiltInFunctions.ILMath.counter(int[])"/> /// you need to specify parameters <paramref name="start"/> and <paramref name="increments"/> explicitly as double value:</para> /// <example><code> /// // This will create elements counting from 1...24: /// <![CDATA[ILArray<double>]]> A = ILMath.counter(4,3,2); /// // This will create elements counting from 1...48 with intervals of 2.0: /// <![CDATA[ILArray<double>]]> A = ILMath.counter(1.0,2.0,4,3,2); /// // ... but this will (by mistake) call the wrong function: /// <![CDATA[ILArray<double>]]> A = ILMath.counter(1,2,4,3,2); /// // ... and therefore create an array of size [1,2,4,3,2] with elements counting from one! /// </code></example> </remarks> public static ILArray<double> counter (double start, double increment, params int[] dimensions) { ILDimension dimRet = new ILDimension(dimensions); double [] retArr = ILMemoryPool.Pool.New<double>(dimRet.NumberOfElements); double val = start; unsafe { fixed (double* pRetArr = retArr) { double* pRetArray = pRetArr; double* pEnd = pRetArr + retArr.Length; while (pRetArray < pEnd) { *pRetArray++ = val; val += increment; } } } return new ILArray<double>(retArr,dimRet); }
/// <summary> /// Create array initialized with all elements set to one. /// </summary> /// <param name="type">Numeric type specification. One value out of the types listed in the <see cred="ILNumerics.NumericType"/> /// enum.</param> /// <param name="dimensions">Dimension specification. At least one dimension must be specified.</param> /// <returns>ILArray<BaseT> of inner type corresponding to <paramref name="type"/> argument.</returns> /// <remarks>The array returned may be cast to the appropriate actual type afterwards. /// <para> /// <list type="number"> /// <listheader>The following types are supported: </listheader> /// <item>Double</item> /// <item>Single</item> /// <item>Complex</item> /// <item>FComplex</item> /// <item>Byte</item> /// <item>Char</item> /// <item>Int16</item> /// <item>Int32</item> /// <item>Int64</item> /// <item>UInt16</item> /// <item>UInt32</item> /// <item>UInt64</item> /// </list> /// </para> /// </remarks> public static ILBaseArray ones(NumericType type, params int[] dimensions) { if (dimensions.Length < 1) throw new ILArgumentException("ones: invalid dimension specified!"); switch (type) { case NumericType.Double: return ones(dimensions); case NumericType.Single: ILDimension dim = new ILDimension(dimensions); unsafe { float[] data = null; data = new float[dim.NumberOfElements]; fixed(float* pD = data) { float* pStart = pD; float* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1.0f; } } return new ILArray<float>(data, dimensions); } case NumericType.Complex: dim = new ILDimension(dimensions); unsafe { complex[] data = null; data = new complex[dim.NumberOfElements]; fixed(complex* pD = data) { complex* pStart = pD; complex* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = new complex(1.0,1.0); } } return new ILArray<complex>(data, dimensions); } case NumericType.FComplex: dim = new ILDimension(dimensions); unsafe { fcomplex[] data = null; data = new fcomplex[dim.NumberOfElements]; fixed(fcomplex* pD = data) { fcomplex* pStart = pD; fcomplex* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = new fcomplex(1.0f,1.0f); } } return new ILArray<fcomplex>(data, dimensions); } case NumericType.Byte: dim = new ILDimension(dimensions); unsafe { byte[] data = null; data = new byte[dim.NumberOfElements]; fixed(byte* pD = data) { byte* pStart = pD; byte* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<byte>(data, dimensions); } case NumericType.Char: dim = new ILDimension(dimensions); unsafe { char[] data = null; data = new char[dim.NumberOfElements]; fixed(char* pD = data) { char* pStart = pD; char* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = Char.MinValue; } } return new ILArray<char>(data, dimensions); } case NumericType.Int16: dim = new ILDimension(dimensions); unsafe { Int16[] data = null; data = new Int16[dim.NumberOfElements]; fixed(Int16* pD = data) { Int16* pStart = pD; Int16* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<Int16>(data, dimensions); } case NumericType.Int32: dim = new ILDimension(dimensions); unsafe { Int32[] data = null; data = new Int32[dim.NumberOfElements]; fixed(Int32* pD = data) { Int32* pStart = pD; Int32* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<Int32>(data, dimensions); } case NumericType.Int64: dim = new ILDimension(dimensions); unsafe { Int64[] data = null; data = new Int64[dim.NumberOfElements]; fixed(Int64* pD = data) { Int64* pStart = pD; Int64* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<Int64>(data, dimensions); } case NumericType.UInt16: dim = new ILDimension(dimensions); unsafe { UInt16[] data = null; data = new UInt16[dim.NumberOfElements]; fixed(UInt16* pD = data) { UInt16* pStart = pD; UInt16* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<UInt16>(data, dimensions); } case NumericType.UInt32: dim = new ILDimension(dimensions); unsafe { UInt32[] data = null; data = new UInt32[dim.NumberOfElements]; fixed(UInt32* pD = data) { UInt32* pStart = pD; UInt32* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<UInt32>(data, dimensions); } case NumericType.UInt64: dim = new ILDimension(dimensions); unsafe { UInt64[] data = null; data = new UInt64[dim.NumberOfElements]; fixed(UInt64* pD = data) { UInt64* pStart = pD; UInt64* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<UInt64>(data, dimensions); } } return null; }
/// <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<Int64> diff(int leadDim, ILArray<Int64> A) { if (A.IsEmpty) return ILArray<Int64> .empty(A.Dimensions); if (A.IsScalar) return ILArray<Int64> .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<Int64> .empty(outDims); } ILArray<Int64> ret; ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); if (inDim[leadDim] == 1) return ILArray<Int64> .empty(0,0); int newLength; Int64 [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] --; newLength = newLength * newDims[leadDim]; retDblArr = ILMemoryPool.Pool.New< Int64 >(newLength); ILDimension newDimension = new ILDimension(newDims); int leadDimLen = inDim[leadDim]; int nrHigherDims = inDim.NumberOfElements / leadDimLen; int incOut = newDimension.SequentialIndexDistance(leadDim); Int64 firstVal, secVal; if (A.IsVector) return A["1:end"] - A[vector(0,A.Length-2)]; if (A.IsReference) { #region Reference storage // ======================== REFERENCE Storage =========== ///////////////////////////// ARBITRARY DIMENSIONS ////////// unsafe { ILIndexOffset idxOffset = A.m_indexOffset; int[] curPosition = new int[A.Dimensions.NumberOfDimensions]; fixed (int* leadDimStart = idxOffset[leadDim]) { fixed ( Int64 * pOutArr = retDblArr) fixed ( Int64 * pInArr = A.m_data) { Int64 * tmpOut = pOutArr; Int64 * lastElementOut = tmpOut + retDblArr.Length - 1; Int64 * tmpIn = pInArr + A.m_indexOffset.Map(0); int* leadDimIdx = leadDimStart; int* leadDimEnd = leadDimStart + leadDimLen; int dimLen = curPosition.Length; int d, curD, posCounter = A.Dimensions.NumberOfElements / leadDimLen; // start at first element while (posCounter --> 0) { leadDimIdx = leadDimStart; firstVal = *(tmpIn + *leadDimIdx++); while (leadDimIdx < leadDimEnd) { secVal = *(tmpIn + *leadDimIdx++); *tmpOut = ( Int64 )(secVal - firstVal); tmpOut += incOut; firstVal = secVal; } if (tmpOut > lastElementOut) tmpOut -= (retDblArr.Length - 1); // increment higher dimensions d = 1; while (d < dimLen) { curD = (d + leadDim) % dimLen; curPosition[curD]++; if (curPosition[curD] < idxOffset[curD].Length) { break; } curPosition[curD] = 0; d++; } tmpIn = pInArr + A.m_indexOffset.IndexFromArray(curPosition); } } } } #endregion } else { // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed ( Int64 * pOutArr = retDblArr) fixed ( Int64 * pInArr = A.m_data) { Int64 * lastElement; Int64 * tmpOut = pOutArr; Int64 * tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; firstVal = *tmpIn++; while (tmpIn < lastElement) { secVal = *tmpIn++; *(tmpOut++) = ( Int64 )(secVal-firstVal); firstVal = secVal; } } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed ( Int64 * pOutArr = retDblArr) fixed ( Int64 * pInArr = A.m_data) { Int64 * lastElementOut = newLength + pOutArr -1; int inLength = inDim.NumberOfElements -1; Int64 * lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); Int64 * tmpOut = pOutArr; int outLength = newLength - 1; Int64 * leadEnd; Int64 * tmpIn = pInArr; for (int h = nrHigherDims; h--> 0; ) { leadEnd = tmpIn + leadDimLen * inc; firstVal = *tmpIn; tmpIn += inc; while (tmpIn < leadEnd) { secVal = *tmpIn; *tmpOut = ( Int64 )(secVal - firstVal); tmpIn += inc; tmpOut += incOut; firstVal = secVal; } if (tmpOut > lastElementOut) tmpOut -= outLength; if (tmpIn > lastElementIn) tmpIn -= inLength; } } } #endregion } } return new ILArray<Int64> (retDblArr, newDimension);; }
/// <summary> /// Create array innitialized with ones /// </summary> /// <param name="type">Numeric type specification. One value out of the types listed in the <see cred="ILNumerics.NumericType"/> /// enum.</param> /// <param name="dimensions">Dimension specification. At least one dimension must be specified.</param> /// <returns>ILArray<BaseT> of inner type corresponding to <paramref name="type"/> argument.</returns> /// <remarks>The array returned may be casted to the actual type accordingly afterwards. /// <para> /// <list type="number"> /// <listheader>The following types are supported: </listheader> /// <item>Double</item> /// <item>Single</item> /// <item>Complex</item> /// <item>FComplex</item> /// <item>Byte</item> /// <item>Char</item> /// <item>Int16</item> /// <item>Int32</item> /// <item>Int64</item> /// <item>UInt16</item> /// <item>UInt32</item> /// <item>UInt64</item> /// </list> /// </para> /// </remarks> public static ILBaseArray ones(NumericType type, params int[] dimensions) { if (dimensions.Length < 1) throw new ILArgumentException("ones: invalid dimension specified!"); switch (type) { case NumericType.Double: return ones(dimensions); case NumericType.Complex: ILDimension dim = new ILDimension(dimensions); unsafe { complex[] data = null; data = new complex[dim.NumberOfElements]; fixed(complex* pD = data) { complex* pStart = pD; complex* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = new complex(1.0,1.0); } } return new ILArray<complex>(data, dimensions); } case NumericType.Byte: dim = new ILDimension(dimensions); unsafe { byte[] data = null; data = new byte[dim.NumberOfElements]; fixed(byte* pD = data) { byte* pStart = pD; byte* pEnd = pD + data.Length; while (pEnd > pStart) { *(--pEnd) = 1; } } return new ILArray<byte>(data, dimensions); } } return null; }
/// <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);; }
/// <summary> /// Compares the size of this dimension to another dimension object. /// </summary> /// <param name="dim2">ILDimension object to compare this to.</param> /// <returns>Returns true if the sizes are the same, else returns false. /// The comparison is made by recognizing singleton dimensions. Therefore /// only non singleton dimensions are compared in the order of their /// appearance. </returns> /// <remarks>The function reutrns true, if the squeezed dimensions of /// both ILDimensions match.</remarks> public bool IsSameSize(ILDimension dim2) { if (dim2.NumberOfElements != m_numberOfElements) return false; for (int d2 = dim2.NumberOfDimensions,d1 = m_nrDims;d1 >= 0;) { d1--; d2--; while (d1 >= 0 && m_dims[d1]== 1) d1--; while (d2 >= 0 && dim2[d2] == 1) d2--; if (d1 >= 0 && d2 >= 0) { if (m_dims[d1] != dim2[d2]) return false; } } return true; }
/// <summary> /// Compares the shape of this dimension to another dimension object /// </summary> /// <param name="dim2">ILDimension object to compare this to.</param> /// <returns>Returns true if the shapes are the same, else returns false. </returns> /// <remarks>This function is more strict than IsSameSize. In order /// for two dimensions to have the same shape, ALL dimensions must match - /// even singleton dimensions.</remarks> public bool IsSameShape(ILDimension dim2) { if (dim2.NumberOfElements != m_numberOfElements) return false; if (dim2.NumberOfDimensions != m_nrDims) return false; for (int d1 = m_nrDims;d1-->0;) { if (m_dims[d1] != dim2.m_dims[d1]) return false; } return true; }
/// <summary> /// Clone ILDimension object. /// </summary> /// <return> /// New ILDimension object as exact copy of this object. /// </return> private ILDimension Clone() { ILDimension ret = new ILDimension(this); return ret; }
/// <summary> /// Clone ILDimension object. /// </summary> /// <return> /// New ILDimension object as exact copy of this object. /// </return> private ILDimension Clone() { ILDimension ret = new ILDimension(this); return(ret); }
/// <summary> /// random n-dimensional array elements /// </summary> /// <param name="dimensions">int array or single int paramters specifying /// dimensions for new array to be created</param> /// <returns>n-dimensional array filled with random numbers.</returns> /// <remarks>the elements lay within the range 0.0 ... 1.0 and are uniformly /// distributed.</remarks> public static ILArray<double> Rand(params int[] dimensions) { ILDimension dim = new ILDimension(dimensions); double[] data = new double[dim.NumberOfElements]; unsafe { fixed (double* pRetArray = data) { double* pCurIdx = pRetArray; double* pLastElement = pCurIdx + dim.NumberOfElements; Random r = new Random((int)System.Environment.TickCount); while (pCurIdx < pLastElement) *pCurIdx++ = r.NextDouble(); } } return new ILArray<double>(data, dimensions); }
/// <summary> /// Create array initialized with all elements set to zero. /// </summary> /// <param name="dimensions">Dimension specification.</param> /// <returns>Zeros-filled array.</returns> public static ILArray<double> zeros(ILDimension dimensions) { return zeros(dimensions.ToIntArray()); }
/// <summary> /// Pseudo random N-dimensional array elements. /// </summary> /// <param name="dimensions">int array or single int paramters specifying /// dimensions for new array to be created.</param> /// <returns>N-dimensional array filled with random numbers.</returns> /// <remarks><para>The elements lie within the range 0.0 ... 1.0 and are uniformly /// distributed.</para> /// <para>The initial seed will be set to Environment.TickCount on the first call.</para></remarks> public static ILArray<double> rand(params int[] dimensions) { ILDimension dim = new ILDimension(dimensions); double[] data = ILMemoryPool.Pool.New<double>(dim.NumberOfElements); if (m_randomGenerator == null) { m_randomGenerator = new Random(System.Environment.TickCount); } unsafe { fixed (double* pRetArray = data) { double* pCurIdx = pRetArray; double* pLastElement = pCurIdx + dim.NumberOfElements; while (pCurIdx < pLastElement) *pCurIdx++ = m_randomGenerator.NextDouble(); } } return new ILArray<double>(data, dimensions); }
/// <summary> /// Elementwise logical 'not equal' operator /// </summary> /// <param name="A">input array 1</param> /// <param name="B">input array 2</param> /// <returns>Logical array having '1' for elements in A not equal elements in B, '0' else</returns> /// <remarks><para>On empty input - empty array will be returned.</para> /// <para>A and / or B may be scalar. The scalar value will operate on all elements of the other arrays in this case.</para> /// <para>If neither of A or B is scalar or empty, the dimensions of both arrays must match.</para></remarks> /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">if neither of A or B is scalar and the size of both arrays does not match</exception> public static ILLogicalArray neq (ILArray<String> A, ILArray<String> B) { if (object.Equals(A,null)) throw new ILArgumentException("neq: input argurment A must not be null!"); if (object.Equals(B,null)) throw new ILArgumentException("neq: input argurment B must not be null!"); if (!A.Dimensions.IsSameShape(B.Dimensions)) throw new ILArgumentException("input arrays must have the same size"); if (A.IsEmpty || B.IsEmpty) return ILLogicalArray.empty(A.Dimensions); ILLogicalArray ret = null; string scalarValue; ILDimension retDim = null; byte[] retArr = null; if (A.IsScalar) { if (B.IsScalar) { retDim = new ILDimension(1,1); ret = new ILLogicalArray(new byte[1]{(A.GetValue(0) != B.GetValue(0))?(byte)1:(byte)0},1,1); } else { retDim = B.Dimensions; int len = B.Dimensions.NumberOfElements; retArr = new byte[len]; scalarValue = A.GetValue(0); for (int i = 0; i < len; i++) { if (scalarValue != B.GetValue(i)) { retArr[i] = 1; } } } } else { retDim = A.Dimensions; if (B.IsScalar) { int len = A.Dimensions.NumberOfElements; retArr = new byte[len]; scalarValue = B.GetValue(0); for (int i = 0; i < len; i++) { if (scalarValue != A.GetValue(i)) retArr[i] = 1; } } else { if (!A.Dimensions.IsSameSize(B.Dimensions)) throw new ILDimensionMismatchException("neq: size of arrays must match!"); int len = A.Dimensions.NumberOfElements; retArr = new byte[len]; for (int i = 0; i < len; i++) { if (A.GetValue(i) != B.GetValue(i)) retArr[i] = 1; } } } return new ILLogicalArray(retArr,retDim); }
/// <summary> /// Normal randomly-distributed N-dimensional array elements. /// </summary> /// <param name="dimensions">int array or single int paramters specifying /// dimensions for new array to be created.</param> /// <returns>N-dimensional array filled with random numbers.</returns> /// <remarks>The elements lie within the range 0.0 ... 1.0 and are choosen to be normally /// distributed.</remarks> public static ILArray<double> randn(params int[] dimensions) { ILDimension dim; if (dimensions.Length == 1) dim = new ILDimension(dimensions[0],dimensions[0]); else dim = new ILDimension(dimensions); if (m_nrandomGenerator == null) m_nrandomGenerator = new ILNRandom(Environment.TickCount); double[] data = ILMemoryPool.Pool.New<double>(dim.NumberOfElements); unsafe { fixed (double* pRetArray = data) { double* pCurIdx = pRetArray; double* pLastElement = pCurIdx + dim.NumberOfElements; while (pCurIdx < pLastElement) *pCurIdx++ = m_nrandomGenerator.NextDouble(); } } return new ILArray<double>(data, dim); }
/// <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 ILArray<UInt16> sum ( ILArray<UInt16> A, int leadDim) { if (leadDim >= A.Dimensions.NumberOfDimensions) throw new ILArgumentException("dimension parameter out of range!"); if (A.IsEmpty) return ILArray<UInt16> .empty(A.Dimensions); if (A.IsScalar) { return new ILArray<UInt16> (new UInt16 []{A.GetValue(0)},1,1); } ILDimension inDim = A.Dimensions; int[] newDims = inDim.ToIntArray(); if (inDim[leadDim] == 1) return ( ILArray<UInt16> )A.Clone(); int newLength; UInt16 [] retDblArr; // build ILDimension newLength = inDim.NumberOfElements / newDims[leadDim]; newDims[leadDim] = 1; retDblArr = ILMemoryPool.Pool.New< UInt16 >(newLength); ILDimension newDimension = new ILDimension(newDims); int incOut = newDimension.SequentialIndexDistance(leadDim); int leadDimLen = inDim[leadDim]; int posCounter; int nrHigherDims = inDim.NumberOfElements / leadDimLen; 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 ( UInt16 * pOutArr = retDblArr) fixed ( UInt16 * pInArr = A.m_data) { UInt16 * tmpOut = pOutArr; UInt16 * lastElementOut = tmpOut + retDblArr.Length; UInt16 * 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 = 0; while (leadDimIdx <= leadDimEnd) { UInt16 inVal = *(tmpIn + *leadDimIdx++); /**/ *tmpOut += (UInt16) (inVal) ; } /**/ tmpOut++; } } } } #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 ( UInt16 * pOutArr = retDblArr) fixed ( UInt16 * pInArr = A.m_data) { UInt16 * tmpOut = pOutArr; UInt16 * lastElementOut = tmpOut + retDblArr.Length - 1; UInt16 * tmpIn = pInArr + A.m_indexOffset.Map(0); int* leadDimIdx = leadDimStart; int* leadDimEnd = leadDimStart + leadDimLen; int dimLen = curPosition.Length; int d, curD; // start at first element posCounter = retDblArr.Length; while (posCounter-->0) { leadDimIdx = leadDimStart; *tmpOut = 0; while (leadDimIdx < leadDimEnd){ UInt16 inVal = *(tmpIn + *leadDimIdx++); /**/ *tmpOut += (UInt16) (inVal) ; /**/ } tmpOut += incOut; if (tmpOut > lastElementOut) tmpOut -= (retDblArr.Length - 1); // increment higher dimensions d = 1; while (d < dimLen) { curD = (d + leadDim) % dimLen; curPosition[curD]++; if (curPosition[curD] < idxOffset[curD].Length) { break; } curPosition[curD] = 0; d++; } tmpIn = pInArr + A.m_indexOffset.IndexFromArray(curPosition); } } } } #endregion } // ============================================================== #endregion } else { // physical -> pointer arithmetic if (leadDim == 0) { #region physical along 1st leading dimension unsafe { fixed ( UInt16 * pOutArr = retDblArr) fixed ( UInt16 * pInArr = A.m_data) { UInt16 * lastElement; UInt16 * tmpOut = pOutArr; UInt16 * tmpIn = pInArr; for (int h = nrHigherDims; h-- > 0; ) { lastElement = tmpIn + leadDimLen; *tmpOut = 0; while (tmpIn < lastElement) { UInt16 inVal = *(tmpIn++); /**/ *tmpOut += (UInt16) (inVal) ; } /**/ tmpOut++; } } } #endregion } else { #region physical along abitrary dimension // sum along abitrary dimension unsafe { fixed ( UInt16 * pOutArr = retDblArr) fixed ( UInt16 * pInArr = A.m_data) { UInt16 * lastElementOut = newLength + pOutArr -1; int inLength = inDim.NumberOfElements -1; UInt16 * lastElementIn = pInArr + inLength; int inc = inDim.SequentialIndexDistance(leadDim); UInt16 * tmpOut = pOutArr; int outLength = newLength - 1; UInt16 * leadEnd; UInt16 * tmpIn = pInArr; for (int h = nrHigherDims; h--> 0; ) { leadEnd = tmpIn + leadDimLen * inc; *tmpOut = 0; while (tmpIn < leadEnd) { UInt16 inVal = *(tmpIn); tmpIn += inc; /**/ *tmpOut += (UInt16) (inVal) ; } /**/ tmpOut += inc; if (tmpOut > lastElementOut) tmpOut = pOutArr + ((tmpOut - pOutArr) - outLength); if (tmpIn > lastElementIn) tmpIn = pInArr + ((tmpIn - pInArr) - inLength); } } } #endregion } } return new ILArray<UInt16> (retDblArr, newDims);; }
/// <summary> /// Create N-dimensional array with elements counting from 1. /// </summary> /// <param name="dimensions">Variable int array with dimension specification</param> /// <returns>Array with elements counting from 1 ... dimensions.NumberOfElements</returns> /// <remarks>This function may be used for the convenient creation of arrays for testing purposes.</remarks> public static ILArray<double> counter (params int[] dimensions) { ILDimension dimRet = new ILDimension(dimensions); double [] retArr = ILMemoryPool.Pool.New<double>(dimRet.NumberOfElements); for (int i = 0; i < retArr.Length; ) retArr[i] = ++i; return new ILArray<double>(retArr,dimRet); }
//TODO Add string and ILBaseArray to list of indexing objects /// <summary> /// Creates ILRange from object array containing ints and Slices. /// </summary> /// <param name="dims">Dimension specification</param> /// <param name="rng">Array with range specification</param> /// <param name="side">Specify if this range is applied to left side or right side expressions</param> public ILRange(ILDimension dims, RangeSide side, params object[] rng) { // objects can be slices or integers if (rng.Length < 1) { Resize(0); return; } // expand string range definition to multidimensional array m_range /* * Note: by specifying a range definition for fewer dimensions than * dimensions in dims, subsequent trailing dimensions will be * merged and added to the last dimension of the range. The 'reshaped' * dimension is than considered for output. The decision as to whether the * dimension must be expanded is determined by the limits of those * output dimensions. */ int start, ende, step; int rngLenUse = rng.Length; int tmpValue; Resize(rngLenUse); #region prepare out dimension length int[] outDims = new int[m_nrDims]; if (rng.Length == 1) { outDims[0] = dims.NumberOfElements; } else { if (rng.Length <= dims.NumberOfDimensions) { for (start = 0; start < m_nrDims; start++) { outDims[start] = dims[start]; } for (; start < dims.NumberOfDimensions; start++) { outDims[m_nrDims - 1] *= dims[start]; } } else { for (start = 0; start < dims.NumberOfDimensions; start++) { outDims[start] = dims[start]; } for (; start < rng.Length; start++) { outDims[start] = 1; } } } #endregion m_numberOfElements = 1; RegularSpacedList idxList = new RegularSpacedList(2); for (int d = 0; d < rngLenUse; d++) { int dimsd = outDims[d]; idxList.Clear(); if (rng[d] is int) { // single number specified int singleIndex = (int)(rng[d]); if (singleIndex < 0) throw new ILArgumentException("invalid index for dimension " + d.ToString()); if (singleIndex >= dimsd) { if (side == RangeSide.Right) throw new ILArgumentException("invalid index for dimension " + d.ToString()); else { Expanding = true; if (m_expandDimensions[d] <= singleIndex) m_expandDimensions[d] = singleIndex + 1; } } idxList.Add(singleIndex); } else if (rng[d] is Slice) { if (((Slice)rng[d]).start == null && ((Slice)rng[d]).stop == null && ((Slice)rng[d]).step == null) { #region full dimension m_range[d] = new int[1] { -(dimsd - 1) }; m_numberOfElements *= dimsd; m_regularSpaced[d] = 1; if (dimsd > 1) m_nonSingletonDimensions++; continue; #endregion } else { if (((Slice)rng[d]).step == null) { if (((Slice)rng[d]).start == null) start = 0; else start = (int)(((Slice)rng[d]).start); if (((Slice)rng[d]).stop == null) ende = dimsd - 1; else ende = (int)(((Slice)rng[d]).stop); step = (ende >= start) ? 1 : -1; } else { step = (int)(((Slice)rng[d]).step); if (step > 0) { if (((Slice)rng[d]).start == null) start = 0; else start = (int)(((Slice)rng[d]).start); if (((Slice)rng[d]).stop == null) ende = dimsd - 1; else ende = (int)(((Slice)rng[d]).stop); } else if (step < 0) { if (((Slice)rng[d]).start == null) start = dimsd - 1; else start = (int)(((Slice)rng[d]).start); if (((Slice)rng[d]).stop == null) ende = 0; else ende = (int)(((Slice)rng[d]).stop); } else throw new ILArgumentException("Invalid index for dimension " + d.ToString() + "."); } if (start < 0 || ende < 0) throw new ILArgumentException("Invalid index for dimension " + d.ToString() + "."); if (start >= dimsd || ende >= dimsd) { if (side == RangeSide.Right) throw new ILArgumentException("Invalid index for dimension " + d.ToString() + "."); else { Expanding = true; int tmpVal = (start > ende) ? start : ende; if (m_expandDimensions[d] <= tmpVal) m_expandDimensions[d] = tmpVal + 1; } } if (start <= ende) { if (step > 0) { for (int t = start; t <= ende; t += step) { idxList.Add(t); } } } else { if (step < 0) { for (int t = start; t >= ende; t += step) { idxList.Add(t); } } } } } else { // If ILBaseArray is used to specify a dimension, all dimensions must be specified by ILBaseArrays // Same for strings // Cannot mix and match except Slices and integers throw new ILArgumentException("Cannot combine other indexers with integers and Slices"); } m_range[d] = (int[])idxList.ToArray(); int idxlistcount = idxList.Count; m_numberOfElements *= idxlistcount; m_regularSpaced[d] = (idxList.IsRegularSpaced) ? idxList.RegularSpacing : int.MinValue; if (idxlistcount > 1) m_nonSingletonDimensions++; } }
/// <summary> /// Dimension represented by this ILIndexOffset /// </summary> /// <returns>Dimension object</returns> /// <remarks>This function will introduce a performance penalty, /// since the dimension object will get reconstructed every time called. /// One should therefore cache the dimension externally, if needed.</remarks> public ILDimension GetDimensions() { ILDimension ret; int[] dims = new int[m_idxOffset.Length]; for (int d = m_idxOffset.Length; d-->0;) dims[d] = m_idxOffset[d].Length; ret = new ILDimension(dims); return ret; }