/// <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 <complex> sumall(ILArray <complex> A) { if (object.Equals(A, null)) { throw new ILArgumentException("sumall: argument must not be null!"); } if (A.IsEmpty) { return(ILArray <complex> .empty(0, 0)); } complex retArr = new complex(0.0, 0.0); unsafe { fixed(complex *inArrStart = A.m_data) { complex *inArrWalk = inArrStart; complex *inArrEnd = inArrStart + A.Dimensions.NumberOfElements; while (inArrWalk < inArrEnd) { retArr += *inArrWalk++; } } } return(new ILArray <complex> (new complex [1] { retArr }, 1, 1)); }
/// <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<complex> sumall ( ILArray<complex> A) { if (object.Equals(A,null)) throw new ILArgumentException("sumall: argument must not be null!"); if (A.IsEmpty) { return ILArray<complex> .empty(0,0); } complex retArr = new complex(0.0,0.0) ; if (A.m_indexOffset == null) { unsafe { fixed ( complex * inArrStart = A.m_data) { complex * inArrWalk = inArrStart; complex * inArrEnd = inArrStart + A.Dimensions.NumberOfElements; while (inArrWalk < inArrEnd) { retArr += *inArrWalk++; } } } } else { unsafe { fixed ( complex * inArrStart = A.m_data) { for (int i = A.Dimensions.NumberOfElements; i -->0;) { retArr += *(inArrStart + A.getBaseIndex(i)); } } } } return new ILArray<complex> (new complex [1]{retArr},1,1); }
// Inplace version of rearrange function public void Rearrange(complex *Data, uint N) { // Swap position uint Target = 0; // Process all positions of input signal for (uint Position = 0; Position < N; ++Position) { // Only for not yet swapped entries if (Target > Position) { // Swap entries complex Temp = Data[Target]; Data[Target] = Data[Position]; Data[Position] = Temp; } // Bit mask uint Mask = N; // While bit is set while ((Target & (Mask >>= 1)) != 0) { // Drop bit Target &= ~Mask; } // The current bit is 0 - set it Target |= Mask; } }
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <summary>Complex conjugate of array A</summary> /// <param name="A">input array</param> /// <returns>Complex conjugate of array A</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 ILArray <complex> conj(ILArray <complex> A) { if (A.IsEmpty) { return(ILArray <complex> .empty(A.Dimensions)); } ILDimension inDim = A.Dimensions; complex [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; //retDblArr = new complex [newLength]; retDblArr = ILMemoryPool.Pool.New <complex> (newLength); int leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(complex *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { complex *lastElement = pOutArr + retDblArr.Length; complex *tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) // HC02 { (*tmpOut).real = (*tmpIn).real; (*tmpOut++).imag = (*tmpIn++).imag * -1.0; } } } return(new ILArray <complex> (retDblArr, inDim)); }
/// <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())); }
private static void copy( VectorDescriptor xDescriptor, complex *x, VectorDescriptor yDescriptor, complex *y) { NativeMethods.cblas_zcopy( xDescriptor.Size, x, xDescriptor.Stride, y, yDescriptor.Stride); }
// Scaling of inverse FFT result public void Scale(complex *Data, uint N) { double Factor = 1.0 / (double)N; // Scale all data entries for (uint Position = 0; Position < N; ++Position) { Data[Position] *= Factor; } }
private static void rot( VectorDescriptor xDescriptor, complex *x, VectorDescriptor yDescriptor, complex *y, double c, double s) { NativeMethods.cblas_zdrot( xDescriptor.Size, x, xDescriptor.Stride, y, yDescriptor.Stride, c, s); }
private static void axpy( complex a, VectorDescriptor xDescriptor, complex *x, VectorDescriptor yDescriptor, complex *y) { NativeMethods.cblas_zaxpy( xDescriptor.Size, &a, x, xDescriptor.Stride, y, yDescriptor.Stride); }
private static complex dotu( VectorDescriptor xDescriptor, complex *x, VectorDescriptor yDescriptor, complex *y) { complex result; NativeMethods.cblas_zdotu_sub( xDescriptor.Size, x, xDescriptor.Stride, y, yDescriptor.Stride, &result); return(result); }
/// <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); }
// FORWARD FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output // N - length of input data public bool Forward(complex *Data, uint N) { // Check input parameters if (Data == null || N < 1 || (N & (N - 1)) != 0) { return(false); } // Rearrange Rearrange(Data, N); // Call FFT implementation Perform(Data, N, false); // Succeeded return(true); }
// FORWARD FOURIER TRANSFORM // Input - input data // Output - transform result // N - length of both input data and result public bool Forward(complex *Input, complex *Output, uint N) { // Check input parameters if (Input == null || Output == null || N < 1 || (N & (N - 1)) != 0) { return(false); } // Initialize data Rearrange(Input, Output, N); // Call FFT implementation Perform(Output, N, false); // Succeeded return(true); }
/// <summary> /// invert elements of A, return result as out argument /// </summary> /// <param name="A"></param> /// <param name="outArray"></param> public static void invert(ILArray <complex> A, ILArray <complex> 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(complex *inA1 = A.m_data) fixed(complex * inA2 = outArray.m_data) { complex *pInA1 = inA1; complex *pInA2 = inA2; int c = 0; complex *outEnd = inA2 + outArray.m_data.Length; if (A.IsReference) { while (pInA2 < outEnd) //HC07 { *pInA2++ = (*(pInA1 + A.getBaseIndex(c++)) * (-1.0)); } } else { while (pInA2 < outEnd) //HC11 { *pInA2++ = (*pInA1++ /*HC:*/ *(-1.0)); } } } #endregion array + array } return; }
// INVERSE FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output // N - length of both input data and result // Scale - if to scale result public bool Inverse(complex *Data, uint N, bool Scale /* = true */) { // Check input parameters if (Data == null || N < 1 || (N & (N - 1)) != 0) { return(false); } // Rearrange Rearrange(Data, N); // Call FFT implementation Perform(Data, N, true); // Scale if necessary if (Scale) { this.Scale(Data, N); } // Succeeded return(true); }
// INVERSE FOURIER TRANSFORM // Input - input data // Output - transform result // N - length of both input data and result // Scale - if to scale result public bool Inverse(complex *Input, complex *Output, uint N, bool Scale /* = true */) { // Check input parameters if (Input == null || Output == null || N < 1 || (N & (N - 1)) != 0) { return(false); } // Initialize data Rearrange(Input, Output, N); // Call FFT implementation Perform(Output, N, true); // Scale if necessary if (Scale) { this.Scale(Output, N); } // Succeeded return(true); }
// Rearrange function public void Rearrange(complex *Input, complex *Output, uint N) { // Data entry position uint Target = 0; // Process all positions of input signal for (uint Position = 0; Position < N; ++Position) { // Set data entry Output[Target] = Input[Position]; // Bit mask uint Mask = N; // While bit is set while ((Target & (Mask >>= 1)) != 0) { // Drop bit Target &= ~Mask; } // The current bit is 0 - set it Target |= Mask; } }
// 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())); }
// FFT implementation public void Perform(complex *Data, uint N, bool Inverse /* = false */) { double pi = Inverse ? 3.14159265358979323846 : -3.14159265358979323846; // Iteration through dyads, quadruples, octads and so on... for (uint Step = 1; Step < N; Step <<= 1) { // Jump to the next entry of the same transform factor uint Jump = Step << 1; // Angle increment double delta = pi / (double)Step; // Auxiliary sin(delta / 2) double Sine = System.Math.Sin(delta * .5); // Multiplier for trigonometric recurrence complex Multiplier = complex.create(-2.0 * Sine * Sine, System.Math.Sin(delta)); // Start value for transform factor, fi = 0 complex Factor = complex.create(1.0); // Iteration through groups of different transform factor for (uint Group = 0; Group < Step; ++Group) { // Iteration within group for (uint Pair = Group; Pair < N; Pair += Jump) { // Match position uint Match = Pair + Step; // Second term of two-point transform complex Product = Factor * Data[Match]; // Transform for fi + pi Data[Match] = Data[Pair] - Product; // Transform for fi Data[Pair] += Product; } // Successive transform factor via trigonometric recurrence Factor = Multiplier * Factor + Factor; } } }
/// <summary>Finds finite value elements</summary> /// <param name="A">input array</param> /// <returns>Logical array with 1 if the corresponding elements of input array is finite, 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 isfinite(ILArray <complex> 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 leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(byte *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { byte * lastElement = pOutArr + retDblArr.Length; byte * tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) // HC02 { *tmpOut++ = complex.IsFinite(*tmpIn++) ?(byte)1:(byte)0; } } } return(new ILLogicalArray(retDblArr, inDim)); }
/// <summary>Magnitude of array elements</summary> /// <param name="A">input array</param> /// <returns>Magnitude of array elements</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 ILArray <double> abs(ILArray <complex> A) { if (A.IsEmpty) { return(ILArray <double> .empty(A.Dimensions)); } ILDimension inDim = A.Dimensions; double [] retDblArr; // build ILDimension int newLength = inDim.NumberOfElements; //retDblArr = new double [newLength]; retDblArr = ILMemoryPool.Pool.New <double> (newLength); int leadDimLen = inDim [0]; // physical -> pointer arithmetic unsafe { fixed(double *pOutArr = retDblArr) fixed(complex * pInArr = A.m_data) { double * lastElement = pOutArr + retDblArr.Length; double * tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) // HC02 { *tmpOut++ = complex.Abs(*tmpIn++); } } } return(new ILArray <double> (retDblArr, inDim)); }
private static void scal(double a, VectorDescriptor descriptor, complex *x) { NativeMethods.cblas_zdscal(descriptor.Size, a, x, descriptor.Stride); }
/// <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 <complex> 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(complex * pInArr = A.m_data) { byte * tmpOut = pOutArr; complex *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 = complex.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(complex * pInArr = A.m_data) { byte * tmpOut = pOutArr; byte * tmpOutEnd = tmpOut + retDblArr.Length - 1; complex *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 = complex.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(complex * pInArr = A.m_data) { byte * lastElement = pOutArr + retDblArr.Length; byte * tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) // HC02 { *tmpOut++ = complex.IsInfinity(*tmpIn++) ?(byte)1:(byte)0; } } } #endregion } return(new ILLogicalArray(retDblArr, inDim)); }
private static double nrm2(VectorDescriptor descriptor, complex *x) { return(NativeMethods.cblas_dznrm2(descriptor.Size, x, descriptor.Stride)); }
private static int iamin(VectorDescriptor descriptor, complex *x) { return((int)NativeMethods.cblas_izamin(descriptor.Size, x, descriptor.Stride)); }
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <summary> /// Find nonzero elements in X /// </summary> /// <param name="X">input array to be evaluated</param> /// <param name="limit">number of elements to search for. If this value is <![CDATA[< 0]]> the function /// will return at most 'limit' nonzero elements from the end of the array ordered by ascending index. /// Set to 0 to search full array.</param> /// <param name="C">If not null, the function will return the row indices of nonzero elements /// as main return value. C will therefore hold the column indices of those elements. If X /// has more than 2 dimensions, the column indices will go along the 2nd dimension.</param> /// <param name="V">if not null on entrance, V will hold a copy of the values of nonzero elements returned.</param> /// <returns>Vector containing (sequential) indices of nonzero elements in X. If C was /// not null, return value will contain row indices of nonzero elements. </returns> /// <remarks>The return type of the index vectors is always 'double'. The return type /// of the element vector 'V' depends on the type of input array X. V and C may be null on /// entrance, indicating their information is not needed. If V is not null (f.e. 'empty()') C must be /// not null also. Any initial data of V or C will be lost.</remarks> public static ILArray <double> find(ILArray <complex> X, int limit, ref ILArray <double> C, ref ILArray <complex> V) { double[] retArray; bool create_row_columns = !Object.Equals(C, null); bool return_values = !Object.Equals(V, null); ILArray <double> ret = null; ILDimension inDim = X.Dimensions; if (inDim.NumberOfElements == 1) { #region SCALAR // scalar -> return copy if (X.GetValue(0, 0).real != 0.0 || X.GetValue(0, 0).imag != 0.0) { retArray = new double[1] { 0 }; if (create_row_columns) { C = new ILArray <double>(0.0); } if (return_values) { V = new ILArray <complex> (new complex [1] { X.GetValue(0, 0) }); } return(new ILArray <double>(retArray, 1, 1)); } else { if (create_row_columns) { C = ILArray <double> .empty(0, 0); } if (return_values) { V = ILArray <complex> .empty(0, 0); } return(ILArray <double> .empty(0, 0)); } #endregion SCALAR } double[] indices; int nrElements = inDim.NumberOfElements; if (limit != 0) { int lim = Math.Abs(limit); if (lim < nrElements) { nrElements = lim; } } indices = ILMemoryPool.Pool.New <double>(nrElements); // init return array with most elements for non logical inarray -> shorten afterwards int foundIdx = 0; #region physical // physical -> pointer arithmetic if (limit >= 0) { unsafe { fixed(double *pIndices = indices) fixed(complex * pX = X.m_data) { complex *lastElement = pX + inDim.NumberOfElements; complex *tmpIn = pX; double * pI = pIndices; double * pFoundLast = pI + indices.Length; while (tmpIn < lastElement && pI < pFoundLast) { if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0) { *pI++ = (double)(tmpIn - pX); } tmpIn++; } foundIdx = (int)(pI - pIndices); } } } else { // search backwards unsafe { fixed(double *pIndices = indices) fixed(complex * pX = X.m_data) { complex *lastElementX = pX; complex *tmpIn = pX + inDim.NumberOfElements; double * pI = pIndices + indices.Length; while (tmpIn > lastElementX && pI > pIndices) { tmpIn--; if ((*tmpIn).real != 0.0 || (*tmpIn).imag != 0.0) { *(--pI) = (double)(tmpIn - pX); } } foundIdx = (int)(pIndices + indices.Length - pI); } } } #endregion if (foundIdx == 0) { // return empty array return(ILArray <double> .empty(0, 0)); } // transform to row / columns; extract values if needed int leadDimLen = inDim[0]; if (create_row_columns) { #region RETURN ROWS / COLUMNS /VALUES C = new ILArray <double> (ILMemoryPool.Pool.New <double>(foundIdx), foundIdx, 1); ret = new ILArray <double> (ILMemoryPool.Pool.New <double>(foundIdx), foundIdx, 1); if (return_values) { V = new ILArray <complex> (ILMemoryPool.Pool.New <complex>(foundIdx), foundIdx, 1); // copy values, transform to row/columns unsafe { fixed(double *pIndices = indices, pRows = ret.m_data, pCols = C.m_data) fixed(complex * pValues = V.m_data, pInput = X.m_data) { double *pI = (limit >= 0) ? pIndices : (pIndices + indices.Length - foundIdx); double * pLastIndex = pIndices + foundIdx; double * pR = pRows; double * pC = pCols; complex *pV = pValues; complex *pX = pInput; while (pI < pLastIndex) { *pR++ = *(pI) % leadDimLen; *pC++ = (int)*(pI) / leadDimLen; *pV++ = *(pInput + (int)*pI++); } } } } else { // just return row / columns unsafe { fixed(double *pIndices = indices, pRows = ret.m_data, pCols = C.m_data) fixed(complex * pInput = X.m_data) { double *pI = (limit >= 0) ? pIndices : (pIndices + indices.Length - foundIdx); double *pLastIndex = pIndices + foundIdx; double *pR = pRows; double *pC = pCols; while (pI < pLastIndex) { *pR++ = *(pI) % leadDimLen; *pC++ = (int)(*(pI++) / leadDimLen); } } } } #endregion RETURN ROWS / COLUMNS } else { #region RETURN INDICES ONLY if (foundIdx != indices.Length) { ret = new ILArray <double> (ILMemoryPool.Pool.New <double>(foundIdx), foundIdx, 1); unsafe { fixed(double *pIndices = indices, pRows = ret.m_data) { double *pI = (limit >= 0) ? pIndices : (pIndices + indices.Length - foundIdx); double *pLastIndex = pIndices + foundIdx; double *pR = pRows; while (pI < pLastIndex) { *pR++ = *pI++; } } } } else { ret = new ILArray <double> (indices, foundIdx, 1); } #endregion RETURN INDICES ONLY } return(ret); }
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <summary> sum two arrays elementwise</summary> /// <param name="A">input 1</param> /// <param name="B">input 2</param> /// <returns> Array with elementwise sum of A and B </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> public static ILArray <complex> subtract(ILArray <complex> A, ILArray <complex> B) { if (A.IsEmpty) { return(ILArray <complex> .empty(A.Dimensions)); } if (B.IsEmpty) { return(ILArray <complex> .empty(B.Dimensions)); } if (A.IsScalar) { if (B.IsScalar) { return(new ILArray <complex> (new complex [1] { (A.m_data[0] - B.m_data[0]) })); } else { #region scalar + array ILDimension inDim = B.Dimensions; complex [] retArr = ILMemoryPool.Pool.New <complex> (inDim.NumberOfElements); complex scalarValue = A.m_data[0]; unsafe { fixed(complex *pOutArr = retArr) fixed(complex * pInArr = B.m_data) { complex *lastElement = pOutArr + retArr.Length; complex *tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) //HC03 { *tmpOut++ = (scalarValue - (*tmpIn++)); } } } return(new ILArray <complex> (retArr, inDim)); #endregion scalar + array } } else { if (B.IsScalar) { #region array + scalar ILDimension inDim = A.Dimensions; complex [] retArr = ILMemoryPool.Pool.New <complex> (A.m_data.Length); complex scalarValue = B.m_data[0]; unsafe { fixed(complex *pOutArr = retArr) fixed(complex * pInArr = A.m_data) { complex *lastElement = pOutArr + retArr.Length; complex *tmpOut = pOutArr; complex *tmpIn = pInArr; while (tmpOut < lastElement) //HC06 { *tmpOut++ = (*tmpIn++ - scalarValue); } } } return(new ILArray <complex> (retArr, inDim)); #endregion array + scalar } else { #region array + array ILDimension inDim = A.Dimensions; if (!inDim.IsSameSize(B.Dimensions)) { throw new ILDimensionMismatchException(); } complex [] retSystemArr = ILMemoryPool.Pool.New <complex> (inDim.NumberOfElements); unsafe { fixed(complex *pOutArr = retSystemArr) fixed(complex * inA1 = A.m_data) fixed(complex * inA2 = B.m_data) { complex *pInA1 = inA1; complex *pInA2 = inA2; complex *poutarr = pOutArr; complex *outEnd = poutarr + retSystemArr.Length; while (poutarr < outEnd) //HC11 { *poutarr++ = (*pInA1++ - (*pInA2++)); } } } return(new ILArray <complex> (retSystemArr, inDim)); #endregion array + array } } }
/// <summary> /// convert arbitrary numeric array to arbitrary numeric type /// </summary> /// <param name="X">input array</param> /// <param name="outputType">type description for return type</param> /// <returns>converted array</returns> /// <remarks> The newly created array will be converted to the type requested. /// <para>Important note: if X matches the type requested, NO COPY will be made for it and the SAME array will be returned!</para></remarks> public static ILBaseArray convert(NumericType outputType, ILArray </*!HC:inType1*/ double> X) { if (outputType == /*!HC:inTypeName*/ NumericType.Double) { return(X); } ILBaseArray ret = null; switch (outputType) { case NumericType.Double: unsafe { double [] retA = ILMemoryPool.Pool.New <double>(X.Dimensions.NumberOfElements); fixed(double *pretA = retA) fixed(/*!HC:inType1*/ double *pX = X.m_data) { double *pStartR = pretA; double *pEndR = pretA + X.m_data.Length; /*!HC:inType1*/ double *pWalkX = pX; while (pStartR < pEndR) { *(pStartR++) = (double)*(pWalkX++); } } ret = new ILArray <double> (retA, X.Dimensions); } return(ret); case NumericType.Complex: unsafe { complex [] retA = ILMemoryPool.Pool.New <complex>(X.Dimensions.NumberOfElements); fixed(complex *pretA = retA) fixed(/*!HC:inType1*/ double *pX = X.m_data) { complex *pStartR = pretA; complex *pEndR = pretA + X.m_data.Length; /*!HC:inType1*/ double *pWalkX = pX; while (pStartR < pEndR) { *(pStartR++) = (complex)(*(pWalkX++)); } } ret = new ILArray <complex> (retA, X.Dimensions); } return(ret); case NumericType.Byte: unsafe { byte [] retA = ILMemoryPool.Pool.New <byte>(X.Dimensions.NumberOfElements); fixed(byte *pretA = retA) fixed(/*!HC:inType1*/ double *pX = X.m_data) { byte *pStartR = pretA; byte *pEndR = pretA + X.m_data.Length; /*!HC:inType1*/ double *pWalkX = pX; while (pStartR < pEndR) { *(pStartR++) = (byte)*(pWalkX++); } } ret = new ILArray <byte> (retA, X.Dimensions); } return(ret); } return(ret); }
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <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 <complex> multiply(ILArray <complex> A, ILArray <complex> B) { ILArray <complex> 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; complex [] 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 complex [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 <complex> (retArr, new ILDimension(A.m_dimensions[0], B.m_dimensions[1])); if (transA == 't') { spacingA1 = spacingA0; } if (transB == 't') { spacingB1 = spacingB0; } unsafe { fixed(complex *ptrC = retArr) fixed(complex * pA = A.m_data) fixed(complex * pB = B.m_data) { complex *ptrA = pA + A.getBaseIndex(0); complex *ptrB = pB + B.getBaseIndex(0); if (transA == 't') { spacingA1 = spacingA0; } if (transB == 't') { spacingB1 = spacingB0; } Lapack.zgemm(transA, transB, A.m_dimensions[0], B.m_dimensions[1], A.m_dimensions[1], ( complex )1.0, (IntPtr)ptrA, spacingA1, (IntPtr)ptrB, spacingB1, ( complex )1.0, retArr, A.m_dimensions[0]); } } return(ret); } } // do GEMM by hand retArr = new complex [A.m_dimensions[0] * B.m_dimensions[1]]; ret = new ILArray <complex> (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(complex *ptrC = retArr) { complex *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); }
/// <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));; }