Как преобразовать ILArray в двойной массив [,]?

Как преобразовать ILArray в двойной массив [,]

я имею ILArray<double> A хочу использовать A.ToArray(), но не знаю, как его использовать

Мне нужно получить double[,] System.Array,

1 ответ

Там нет естественной поддержки для преобразования ILArray<double> в многомерный System.Array double[,] в ILNumerics в настоящее время. Итак, давайте напишем это!

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;
    }
}

Эта функция должна работать на произвольной ILArray<T> произвольного типа элемента и произвольных размеров / размеров. (Однако, как всегда, вы должны провести обширное тестирование, прежде чем начать продуктивную работу!). Он создает новый массив System.Array нужного размера и типа и копирует все элементы в их естественном порядке (расположение хранилища). Возвращенный System.Array впоследствии может быть приведен к истинному многомерному массиву.

Мы используем Buffer.BlockCopy для того, чтобы скопировать элементы. Помните, что System.Array хранит свои элементы в основном порядке строк. ILNumerics (так же, как FORTRAN, Matlab и другие) предпочитает основной порядок столбцов! Таким образом, поскольку мы просто быстро копируем элементы и не пытаемся упорядочить их в памяти, исходящий массив будет отображаться с измененными размерами по сравнению с входным массивом:

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

exp будет размером [3 х 4]. Для матриц это можно легко обойти путем транспонирования входного массива:

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

@Edit: исправление: использовался Marshal.Sizeof(T) вместо sizeof(double) @Edit: исправление: теперь исправлено: использовалось Marshal.Sizeof(typeof(T))

Другие вопросы по тегам