Как преобразовать 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))