From d7979cc2759d139d2e3c7ab084fa6887b3e9cb4d Mon Sep 17 00:00:00 2001
From: "Joern Ungermann (IEK-7 FZ-Juelich)" <j.ungermann@fz-juelich.de>
Date: Thu, 28 Nov 2013 15:12:33 +0100
Subject: [PATCH] Added numerical core routines for Jacobian multiply.

---
 pyramid/numcore/phase_mag_real.pyx | 63 +++++++++++++++++++++++++++++-
 pyramid/phasemapper.py             | 16 ++++++++
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/pyramid/numcore/phase_mag_real.pyx b/pyramid/numcore/phase_mag_real.pyx
index d679933..a0403f5 100644
--- a/pyramid/numcore/phase_mag_real.pyx
+++ b/pyramid/numcore/phase_mag_real.pyx
@@ -92,8 +92,8 @@ def get_jacobi_core(
 @cython.wraparound(False)
 def get_jacobi_core(
     unsigned int v_dim, unsigned int u_dim,
-    np.ndarray v_phi, np.ndarray u_phi,
-    np.ndarray jacobi):
+    double[:, :] v_phi, double[:, :] u_phi,
+    double[:, :] jacobi):
     '''DOCSTRING!'''
     # TODO: Docstring!!!
     cdef unsigned int i, j, p, q, p_min, p_max, q_min, q_max, u_column, v_column, row
@@ -105,3 +105,62 @@ def get_jacobi_core(
             # v_dim*u_dim columns for the v-component (note the minus!):
             jacobi[:, u_dim*v_dim+i+u_dim*j] = \
                 -np.reshape(v_phi[v_dim-1-j:(2*v_dim-1)-j, u_dim-1-i:(2*u_dim-1)-i], -1)
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def multiply_jacobi_core(
+    unsigned int v_dim, unsigned int u_dim,
+    double[:, :] v_phi, double[:, :] u_phi,
+    double[:] vector,
+    double[:] result):
+
+    cdef unsigned int s, i, j, u_min, u_max, v_min, v_max, ri, u, v, siz
+    cdef double v0, v1
+    siz = u_dim * v_dim
+
+    s = 0
+    for i in range(u_dim):
+        for j in range(v_dim):
+            u_min = (u_dim - 1) - i
+            v_min = (v_dim - 1) - j
+
+            ri = 0
+            for v in range(v_min, v_min + v_dim):
+                for u in range(u_min, u_min + u_dim):
+                    result[ri] += vector[s] * u_phi[v, u]
+                    result[ri] -= vector[s + siz] * v_phi[v, u]
+                    ri += 1
+            s += 1
+
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def multiply_jacobi_core2(
+    int v_dim, int u_dim,
+    double[:, :] v_phi, double[:, :] u_phi,
+    double[:] vector,
+    double[:] result):
+
+    cdef int s1, s2, i, j, u_min, u_max, v_min, v_max, ri, u, v, siz, j_min, j_max, i_min, i_max
+
+    siz = u_dim * v_dim
+
+    for v in range(2 * v_dim - 1):
+        for u in range(2 * u_dim - 1):
+            i_min = max(0, (u_dim - 1) - u)
+            i_max = min(u_dim, ((2 * u_dim) - 1) - u)
+            for i in range(i_min, i_max):
+                s1 = i * u_dim
+                s2 = s1 + siz
+
+                j_min = max(0, (v_dim - 1) - v)
+                j_max = min(v_dim, ((2 * v_dim) - 1) - v)
+
+                u_min = (u_dim - 1) - i
+                v_min = (v_dim - 1) - j_min
+                ri = (v - ((v_dim - 1) - j_min)) * u_dim + (u - u_min)
+                for j in range(j_min, j_max):
+                    result[ri] += vector[s1 + j] * u_phi[v, u]
+                    result[ri] -= vector[s2 + j] * v_phi[v, u]
+                    ri += u_dim
diff --git a/pyramid/phasemapper.py b/pyramid/phasemapper.py
index 8ddf90b..fdc41c0 100644
--- a/pyramid/phasemapper.py
+++ b/pyramid/phasemapper.py
@@ -99,6 +99,22 @@ class Kernel:
             result += vector[s+size]*-self.v[v_min:v_max, u_min:u_max].reshape(-1)  # v        
         return result
 
+    def multiply_jacobi_core(self, vector):
+        v_dim, u_dim = self.dim
+        size = v_dim * u_dim
+        result = np.zeros(size)
+        nc.multiply_jacobi_core(
+            v_dim, u_dim, self.v, self.u, vector, result)
+        return result
+
+    def multiply_jacobi_core2(self, vector):
+        v_dim, u_dim = self.dim
+        size = v_dim * u_dim
+        result = np.zeros(size)
+        nc.multiply_jacobi_core2(
+            v_dim, u_dim, self.v, self.u, vector, result)
+        return result
+
     def multiply_jacobi_T(self, vector):
         # TODO: Docstring!!!
         # vector: v_dim*u_dim elements for u_mag and v_dim*u_dim elements for v_mag
-- 
GitLab