Мои окончательные решения
После всех испытаний я нашел два слегка отличающихся способа выполнить расчет с достаточной скоростью.
Сначала я использовал функцию diff
с различными типами возвращаемых значений, ниже приведен код, возвращающий вектор, но я также рассчитал версию, возвращающую двойной массив (заменить (vec y) на y) и Incanter.matrix (заменить (vec y) на матрицу y). Эта функция основана только на массивах Java. Это основано на коде Jouni с некоторыми дополнительными подсказками типа.
Другой подход заключается в выполнении вычислений с массивами Java и сохранении значений в переходном векторе. Как видно из времени, это немного быстрее, чем подход 1, если вы не хотите возвращать функцию и массив. Это реализовано в функции difft
.
Так что выбор действительно зависит от того, что вы не хотите делать с данными. Я думаю, что хорошим вариантом было бы перегрузить функцию, чтобы она возвращала тот же тип, который использовался в вызове. На самом деле передача Java-массива в diff вместо вектора делает ~ 1с быстрее.
Времена для различных функций:
Вектор возврата различий:
(time (def y (diff x)))
"Elapsed time: 4733.259 msecs"
diff возвращает Incanter.matrix:
(time (def y (diff x)))
"Elapsed time: 2599.728 msecs"
diff возвращает двойной массив:
(time (def y (diff x)))
"Elapsed time: 1638.548 msecs"
difft:
(time (def y (difft x)))
"Elapsed time: 3683.237 msecs"
Функции
(use 'incanter.stats)
(def x (vec (sample-normal 1e7)))
(defn diff [x]
(let [y (double-array (dec (count x)))
x (double-array x)]
(dotimes [i (dec (count x))]
(aset y i
(- (aget x (inc i))
(aget x i))))
(vec y)))
(defn difft [x]
(let [y (vector (range n))
y (transient y)
x (double-array x)]
(dotimes [i (dec (count x))]
(assoc! y i
(- (aget x (inc i))
(aget x i))))
(persistent! y)))