1 ;; 2d and 3d convolutions
4 (def-generator (convolve-circ (rank type
))
5 `(defun ,name
(vola volb
)
6 (declare ((simple-array ,long-type
,rank
) vola volb
)
7 (values (simple-array ,long-type
,rank
) &optional
))
8 (let* ((da (array-dimensions vola
))
9 (db (array-dimensions volb
))
10 (compare-ab (map 'list
#'(lambda (x y
) (eq x y
)) da db
)))
11 (when (some #'null compare-ab
)
15 "~a expects both input arrays to have the same dimensions." name
)))
16 ;; fta and ftb are both already divided by n, the following ift
17 ;; will introduce will not divide by n so i have to do that
18 (ift (s* (/ ,(coerce 1 (ecase type
(csf 'single-float
) (cdf 'double-float
)))
19 (array-total-size vola
))
20 (.
* (ft vola
) (ft (fftshift volb
))))))))
22 (defmacro def-convolve-circ-functions
(ranks types
)
23 (let* ((specifics nil
)
25 (name (format-symbol "convolve-circ")))
26 (loop for rank in ranks do
27 (loop for type in types do
28 (let ((def-name (format-symbol "def-~a-rank-type" name
))
29 (specific-name (format-symbol "~a-~a-~a" name rank type
)))
30 (push `(,def-name
,rank
,type
) specifics
)
31 (push `((simple-array ,(get-long-type type
) ,rank
)
34 (store-new-function name
)
39 (t (error "The given type can't be handled with a generic ~a function." ',name
)))))))
41 (def-convolve-circ-functions (2 3) (csf cdf
))
44 (defun front (i) ;; extra size needed to accommodate kernel overlap
45 ;; there is a difference between even and odd kernels
47 (values fixnum
&optional
))
54 (def-generator (convolve-nocrop (rank type
))
55 `(defun ,name
(vola volb
)
56 "Convolve VOLA with VOLB. We consider VOLB as the convolution
57 kernel. Returns (values result vec). RESULT is an arrays that is as
58 big as necessary to accommodate the convolution and VEC contains the
59 relative coordinates to find the original sample positions of array
61 (declare ((simple-array ,long-type
,rank
) vola volb
)
62 (values (simple-array ,long-type
,rank
) vec-i
&optional
))
65 (2 `(destructuring-bind (ya xa
) (array-dimensions vola
)
66 (destructuring-bind (yb xb
) (array-dimensions volb
)
67 (let* ((biga (make-array (list (+ ya yb
) (+ xa xb
))
68 :element-type
',long-type
))
69 (bigb (make-array (array-dimensions biga
)
70 :element-type
',long-type
))
75 (start (make-vec-i :x fxb
:y fyb
)))
76 (do-region ((j i
) (ya xa
))
77 (setf (aref biga
(+ j fyb
) (+ i fxb
))
79 (do-region ((j i
) (yb xb
))
80 (setf (aref bigb
(+ j fya
) (+ i fxa
))
82 (values (convolve-circ biga bigb
) start
)))))
83 (3 `(destructuring-bind (za ya xa
) (array-dimensions vola
)
84 (destructuring-bind (zb yb xb
) (array-dimensions volb
)
85 (let* ((biga (make-array (list (+ za zb
) (+ ya yb
) (+ xa xb
))
86 :element-type
',long-type
))
87 (bigb (make-array (array-dimensions biga
)
88 :element-type
',long-type
))
95 (start (make-vec-i :x fxb
:y fyb
:z fzb
)))
96 (do-region ((k j i
) (za ya xa
))
97 (setf (aref biga
(+ k fzb
) (+ j fyb
) (+ i fxb
))
99 (do-region ((k j i
) (zb yb xb
))
100 (setf (aref bigb
(+ k fza
) (+ j fya
) (+ i fxa
))
102 (values (convolve-circ biga bigb
) start
))))))))
104 (defmacro def-convolve-nocrop-functions
(ranks types
)
105 (let* ((specifics nil
)
107 (name (format-symbol "convolve-nocrop")))
108 (loop for rank in ranks do
109 (loop for type in types do
110 (let ((def-name (format-symbol "def-~a-rank-type" name
))
111 (specific-name (format-symbol "~a-~a-~a" name rank type
)))
112 (push `(,def-name
,rank
,type
) specifics
)
113 (push `((simple-array ,(get-long-type type
) ,rank
)
114 (,specific-name a b
))
116 (store-new-function name
)
121 (t (error "The given type can't be handled with a generic ~a function." ',name
)))))))
123 (def-convolve-nocrop-functions (2 3) (csf cdf
))
125 (defun convolve (vola kernel
)
126 (multiple-value-bind (conv start
) (convolve-nocrop vola kernel
)
127 (let* ((s (convert-1-fix/df-mul start
))
128 (d (array-dimensions vola
)) ;; z y x, y x or x
129 (dims (ecase (length d
) ;; ensure 3 entries
130 (1 (push 0 d
) (push 0 d
))
133 (b (convert-1-fix/df-mul
134 (make-array 3 :element-type
'fixnum
;; z y x -> x y z
135 :initial-contents
(reverse dims
)))))
138 :end
(v- (v+ s b
) (v 1 1 1)))))))
141 (let ((a (make-array (list 20 40 30)
142 :element-type
'(complex single-float
)))
143 (b (make-array (list 10 20 30)
144 :element-type
'(complex single-float
))))