How to convert ILArray into double[,] array?

2019-02-25 11:26发布

How convert ILArray into double[,] array

I have ILArray<double> A want to use A.ToArray(), but don't know how to use it

I need to get a double[,] System.Array.

标签: c# ilnumerics
1条回答
叼着烟拽天下
2楼-- · 2019-02-25 11:41

There is no natural support for converting an ILArray<double> into an multi dimensional System.Array double[,] in ILNumerics currently. So let's write it!

private static System.Array ToSystemMatrix<T>(ILInArray<T> A) {
    using (ILScope.Enter(A)) {
        // some error checking (to be improved...)
        if (object.Equals(A, null)) throw new ArgumentException("A may not be null");
        if (!A.IsMatrix) throw new ArgumentException("Matrix expected");

        // create return array
        System.Array ret = Array.CreateInstance(typeof(T), A.S.ToIntArray().Reverse().ToArray());
        // fetch underlying system array
        T[] workArr = A.GetArrayForRead();
        // copy memory block 
        Buffer.BlockCopy(workArr, 0, ret, 0, Marshal.SizeOf(typeof(T)) * A.S.NumberOfElements);
        return ret;
    }
}

This function should work on arbitrary ILArray<T> of arbitrary element type and arbitrary sizes / dimensions. (However, as always, you should do extensive testing before going productive!) It creates a new System.Array of the desired size and type and copies all elements in their natural (storage layout) order. The System.Array returned can get cast to the true multidimensional array afterwards.

We use Buffer.BlockCopy in order to copy the elements. Keep in mind, System.Array stores its elements in row major order. ILNumerics (just like FORTRAN, Matlab and others) prefers column major order! So, since we just copy the elements quickly and do no efforts to reorder them in memory, the outcoming array will appear as having the dimensions flipped in comparison to the input array:

ILArray<double> C = ILMath.counter(4, 3);
var exp = ToSystemMatrix<double>(C); 

exp will be of size [3 x 4]. For matrices, this can easily be circumvented by transposing the input array:

var exp = ToSystemMatrix<double>(C.T); 

@Edit: bugfix: used Marshal.Sizeof(T) instead of sizeof(double) @Edit: bugfix: now fixed the fix: used Marshal.Sizeof(typeof(T))

查看更多
登录 后发表回答