/// <summary> /// sum all elements of array A /// </summary> /// <param name="A">n-dim array</param> /// <returns><para>scalar sum of all elements of A.</para> /// <para>If A is empty, an empty array will be returned.</para></returns> /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A was null.</exception> /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.sum(ILArray<double>)"/> public static ILArray<fcomplex> sumall ( ILArray<fcomplex> A) { if (object.Equals(A,null)) throw new ILArgumentException("sumall: argument must not be null!"); if (A.IsEmpty) { return ILArray<fcomplex> .empty(0,0); } fcomplex retArr = new fcomplex(0.0f,0.0f) ; if (A.m_indexOffset == null) { unsafe { fixed ( fcomplex * inArrStart = A.m_data) { fcomplex * inArrWalk = inArrStart; fcomplex * inArrEnd = inArrStart + A.Dimensions.NumberOfElements; while (inArrWalk < inArrEnd) { retArr += *inArrWalk++; } } } } else { unsafe { fixed ( fcomplex * inArrStart = A.m_data) { for (int i = A.Dimensions.NumberOfElements; i -->0;) { retArr += *(inArrStart + A.getBaseIndex(i)); } } } } return new ILArray<fcomplex> (new fcomplex [1]{retArr},1,1); }
/// <summary> /// invert elements of A, return result as out argument /// </summary> /// <param name="A"></param> /// <param name="outArray"></param> public static void invert(ILArray <fcomplex> A, ILArray <fcomplex> outArray) { #region array + array ILDimension inDim = A.Dimensions; if (!inDim.IsSameSize(outArray.Dimensions)) { throw new ILDimensionMismatchException(); } int leadDim = 0, leadDimLen = inDim [0]; // 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; } } unsafe { fixed(fcomplex *inA1 = A.m_data) fixed(fcomplex * inA2 = outArray.m_data) { fcomplex *pInA1 = inA1; fcomplex *pInA2 = inA2; int c = 0; fcomplex *outEnd = inA2 + outArray.m_data.Length; if (A.IsReference) { while (pInA2 < outEnd) //HC07 { *pInA2++ = (*(pInA1 + A.getBaseIndex(c++)) * (-1.0f)); } } else { while (pInA2 < outEnd) //HC11 { *pInA2++ = (*pInA1++ /*HC:*/ *(-1.0f)); } } } #endregion array + array } return; }
/// <summary>Locate infinite value elements</summary> /// <param name="A">input array</param> /// <returns>Logical array with 1 if the corresponding elements of input array is infinite, 0 else.</returns> /// <remarks><para>If the input array is empty, an empty array will be returned.</para> /// <para>The array returned will be a dense array.</para></remarks> public static ILLogicalArray isinf(ILArray <fcomplex> A) { if (A.IsEmpty) { return(ILLogicalArray.empty(A.Dimensions)); } ILDimension inDim = A.Dimensions; byte [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; //retDblArr = new byte [newLength]; retDblArr = ILMemoryPool.Pool.New <byte> (newLength); int leadDim = 0; int leadDimLen = inDim [0]; if (A.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 = A.m_indexOffset; int incOut = inDim.SequentialIndexDistance(leadDim); System.Diagnostics.Debug.Assert(!A.IsVector, "Reference arrays of vector size should not exist!"); if (A.IsMatrix) { #region Matrix //////////////////////////// MATRIX //////////////////// int secDim = (leadDim + 1) % 2; unsafe { fixed(int *leadDimStart = idxOffset [leadDim], secDimStart = idxOffset [secDim]) { fixed(byte *pOutArr = retDblArr) fixed(fcomplex * pInArr = A.m_data) { byte * tmpOut = pOutArr; fcomplex *tmpIn = pInArr; byte * tmpOutEnd = pOutArr + inDim.NumberOfElements - 1; int * secDimEnd = secDimStart + idxOffset [secDim].Length; int * secDimIdx = secDimStart; int * leadDimIdx = leadDimStart; int * leadDimEnd = leadDimStart + leadDimLen; while (secDimIdx < secDimEnd) { if (tmpOut > tmpOutEnd) { tmpOut = pOutArr + (tmpOut - tmpOutEnd); } tmpIn = pInArr + *secDimIdx++; leadDimIdx = leadDimStart; while (leadDimIdx < leadDimEnd) // HC00 { *tmpOut = fcomplex.IsInfinity(*(tmpIn + *leadDimIdx++)) ?(byte)1:(byte)0; tmpOut += incOut; } } } } } #endregion } else { #region arbitrary size unsafe { int [] curPosition = new int [A.Dimensions.NumberOfDimensions]; fixed(int *leadDimStart = idxOffset [leadDim]) { fixed(byte *pOutArr = retDblArr) fixed(fcomplex * pInArr = A.m_data) { byte * tmpOut = pOutArr; byte * tmpOutEnd = tmpOut + retDblArr.Length - 1; fcomplex *tmpIn = pInArr + A.getBaseIndex(0, 0); tmpIn -= idxOffset [leadDim, 0]; // if the first index of leaddim is not 0, it will be added later anyway. so we subtract it here int *leadDimIdx = leadDimStart; int *leadDimEnd = leadDimStart + leadDimLen; int dimLen = curPosition.Length; int d, curD, count = retDblArr.Length / leadDimLen; // start at first element while (count-- > 0) { leadDimIdx = leadDimStart; while (leadDimIdx < leadDimEnd) //HC01 { *tmpOut = fcomplex.IsInfinity(*(tmpIn + *leadDimIdx++)) ?(byte)1:(byte)0; tmpOut += incOut; } if (tmpOut > tmpOutEnd) { tmpOut -= retDblArr.Length - 1; } // 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 = retDblArr) fixed(fcomplex * pInArr = A.m_data) { byte * lastElement = pOutArr + retDblArr.Length; byte * tmpOut = pOutArr; fcomplex *tmpIn = pInArr; while (tmpOut < lastElement) // HC02 { *tmpOut++ = fcomplex.IsInfinity(*tmpIn++) ?(byte)1:(byte)0; } } } #endregion } return(new ILLogicalArray(retDblArr, inDim)); }
/// <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> /// GEneral Matrix Multiply this array /// </summary> /// <overloads>General Matrix Multiply for double, float, complex and fcomplex arrays</overloads> /// <param name="A"><![CDATA[ILArray<>]]> matrix A</param> /// <param name="B"><![CDATA[ILArray<>]]> matrix B</param> /// <returns><![CDATA[ILArray<double>]]> new array - result of matrix multiplication</returns> /// <remarks>Both arrays must be matrices. The matrix will be multiplied only /// if dimensions match accordingly. Therefore B's number of rows must /// equal A's number of columns. An Exception will be thrown otherwise. /// The multiplication will carried out on BLAS libraries, if availiable and the /// storage memory structure meets BLAS's requirements. If not it will be done inside .NET's /// framework 'by hand'. This is especially true for referencing storages with /// irregular dimensions. However, even GEMM on those reference storages linking into /// a physical storage can (an will) be carried out via BLAS dll's, if the spacing /// into dimensions matches the requirements of BLAS. Those are: /// <list> /// <item>the elements of one dimension will be adjecently layed out, and</item> /// <item>the elements of the second dimension must be regular (evenly) spaced</item> /// </list> /// <para>For reference arrays where the spacing between adjecent elements do not meet the /// requirements above, the matrix multiplication will be made without optimization and /// therefore suffer from low performance in relation to solid arrays. See <a href="http://ilnumerics.net?site=5142">online documentation: referencing for ILNumerics.Net</a></para> /// </remarks> /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">if at least one arrays is not a matrix</exception> /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">if the size of both matrices do not match</exception> public static ILArray <fcomplex> multiply(ILArray <fcomplex> A, ILArray <fcomplex> B) { ILArray <fcomplex> ret = null; if (A.Dimensions.NumberOfDimensions != 2 || B.Dimensions.NumberOfDimensions != 2) { throw new ILArgumentSizeException("Matrix multiply: arguments must be 2-d."); } if (A.Dimensions[1] != B.Dimensions[0]) { throw new ILDimensionMismatchException("Matrix multiply: inner matrix dimensions must match."); } // decide wich method to use // test auf Regelmigkeit der Dimensionen int spacingA0; int spacingA1; int spacingB0; int spacingB1; char transA, transB; fcomplex [] retArr = null; isSuitableForLapack(A, B, out spacingA0, out spacingA1, out spacingB0, out spacingB1, out transA, out transB); if (A.m_dimensions.NumberOfElements > ILAtlasMinimumElementSize || B.m_dimensions.NumberOfElements > ILAtlasMinimumElementSize) { // do BLAS GEMM retArr = new fcomplex [A.m_dimensions[0] * B.m_dimensions[1]]; if (((spacingA0 == 1 && spacingA1 > int.MinValue) || (spacingA1 == 1 && spacingA0 > int.MinValue)) && ((spacingB0 == 1 && spacingB1 > int.MinValue) || (spacingB1 == 1 && spacingB0 > int.MinValue))) { ret = new ILArray <fcomplex> (retArr, new ILDimension(A.m_dimensions[0], B.m_dimensions[1])); if (transA == 't') { spacingA1 = spacingA0; } if (transB == 't') { spacingB1 = spacingB0; } unsafe { fixed(fcomplex *ptrC = retArr) fixed(fcomplex * pA = A.m_data) fixed(fcomplex * pB = B.m_data) { fcomplex *ptrA = pA + A.getBaseIndex(0); fcomplex *ptrB = pB + B.getBaseIndex(0); if (transA == 't') { spacingA1 = spacingA0; } if (transB == 't') { spacingB1 = spacingB0; } Lapack.cgemm(transA, transB, A.m_dimensions[0], B.m_dimensions[1], A.m_dimensions[1], ( fcomplex )1.0, (IntPtr)ptrA, spacingA1, (IntPtr)ptrB, spacingB1, ( fcomplex )1.0, retArr, A.m_dimensions[0]); } } return(ret); } } // do GEMM by hand retArr = new fcomplex [A.m_dimensions[0] * B.m_dimensions[1]]; ret = new ILArray <fcomplex> (retArr, A.m_dimensions[0], B.m_dimensions[1]); unsafe { int in2Len1 = B.m_dimensions[1]; int in1Len0 = A.m_dimensions[0]; int in1Len1 = A.m_dimensions[1]; fixed(fcomplex *ptrC = retArr) { fcomplex *pC = ptrC; for (int c = 0; c < in2Len1; c++) { for (int r = 0; r < in1Len0; r++) { for (int n = 0; n < in1Len1; n++) { *pC += A.GetValue(r, n) * B.GetValue(n, c); } pC++; } } } } return(ret); }