clojure - 将 Java 代码转换为快速的 Clojure 代码

标签 clojure

能否将此 Java 代码转换为同样快或几乎同样快的 Clojure 代码?

我已经能够获得更简单的函数,例如添加两个数组以使用类型提示以合理的速度运行,但是我无法让 Clojure 使用 Java 互操作或 Incanter 在合理的时间内完成下面的功能矩阵并使用函数式或命令式样式。

我是否遗漏了有关类型提示的内容,还是最好在 Java 中执行此类操作?

static double[][] grad2_stencil= { {0,0,-1,0,0}, 
                             {0,0,16,0,0}, 
                             {-1,16,-60,16,-1}, 
                             {0,0,16,0,0}, 
                             {0,0,-1,0,0} };

public static double grad2(double[][] array, int x, int y){
    double temp=0;
    int L=array.length;
    for(int i=0; i<5; i++){
        for(int j=0; j<5; j++){
            temp+=array[((x+i-2)%L+L)%L][((y+j-2)%L+L)%L]*grad2_stencil[i][j];
        }
    }
    return temp/12.0;
}

public static double[][] grad2_field(double[][] arr){
    int L=arr.length;
    double[][] result=new double[L][L];

    for(int i=0; i<L; i++){
        for(int j=0; j<L; j++){
            result[i][j]=grad2(arr, i, j);
        }
    }

    return result;
}

最佳答案

在 clojure 1.3(主分支)中尝试以下操作:

(def ^"[[D" grad2-stencil
  (into-array (Class/forName "[D")
    (map double-array 
      [[ 0   0  -1  0  0 ] 
       [ 0   0  16  0  0 ]
       [-1  16 -60 16 -1 ] 
       [ 0   0  16  0  0 ] 
       [ 0   0  -1  0  0 ]])))

(defn ^:static idx ^long [^long x ^long i ^long L]
  (-> x
    (+ i)
    (- 2)
    (mod L)
    (+ L)
    (mod L)))

(defn ^:static grad2 ^double [^doubles arr ^long x ^long y]
  (let [L (alength arr)
        temp (loop [i 0 j 0 temp 0.0]
               (if (< i 5) 
                 (let [a (idx x i L)
                       b (idx y j L)
                       temp (double (* (aget arr a b) 
                                      (aget grad2-stencil i j)))]
                   (if (< j 4)
                     (recur i (inc j) temp)
                     (recur (inc i) 0 temp)))
                 temp))]
    (/ temp 12.0)))

(defn ^:static grad2-field ^"[[D" [^"[[D" arr]
  (let [result (make-array Double/TYPE (alength arr) (alength arr))]
    (loop [i 0 j 0]
      (when (< i 5)
        (aset result (grad2 arr i j) i j)
        (if (< j 4)
          (recur i (inc j))
          (recur (inc i) 0))))
    result))

关于clojure - 将 Java 代码转换为快速的 Clojure 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3807554/

相关文章:

data-structures - 在 Clojure 中编写需要指针/引用的数据结构?

string - 将整数转换为单词和罗马数字

clojure - 如何正确缩进 clojure/lisp?

Clojure 盒 : Problem with classpath (noob question)

clojure - 如何将唯一性验证与持久层解耦?

clojure - clojure 中的解构 - 嵌入式 map

clojure - 什么是 noir.server/启动选项 :ns for?

clojure - 如何在 Clojure 中定义通用递归函数

Clojure - core.async 合并单向 channel

clojure - "java.lang.IllegalArgumentException: No value supplied for key"的原因是什么?