1 ;; define a bunch of functions to convert an {1,2,3}-dimensional array
2 ;; from one type into another type.
5 ;; for writing several type conversion functions will have a name like
6 ;; convert-3-ub8/cdf-mul the rank is looped over 1, 2 and 3. here the
7 ;; suffix mul indicates that type (up-)conversion is forced by a
8 ;; multiplication. other suffixes are floor for conversion into fixed
9 ;; type and coerce. coerce seemed to be quite slow last time i
10 ;; tried. thats why i prefer the multiplication for most conversions.
12 (def-generator (convert (rank type out_type func short_func
))
13 (let ((long-out-type (get-long-type out_type
))
14 ;; override the name that is constructed by def-generator
15 (name (format-symbol "convert-~a-~a/~a-~a"
18 (store-new-function name
)
20 (declare ((simple-array ,long-type
,rank
) a
)
21 (values (simple-array ,long-out-type
,rank
) &optional
))
22 (let* ((result (make-array (array-dimensions a
)
23 :element-type
(quote ,long-out-type
)))
24 (result1 (sb-ext:array-storage-vector result
))
25 (a1 (sb-ext:array-storage-vector a
))
28 (setf (aref result1 i
)
29 (funcall ,func
(aref a1 i
))))
33 (def-convert-rank-type-out_type-func-short_func
34 1 sf df
#'(lambda (x) (* 1d0 x
)) coerce
)
36 (def-convert-rank-type-out_type-func-short_func
37 1 ub8 csf
#'(lambda (x) (complex (* 1d0 x
))) complex
)
39 (convert-1-sf/df-coerce
40 (make-array 4 :element-type
'single-float
))
43 (defmacro def-convert-functions
()
44 (labels ( ;; create a spec like this: ub8 sf (* 1s0 x) mul
45 ;; down can be used to convert double into float
46 (def (in-type out-type
&optional
(fun t
))
52 (:coerce
`(coerce x
',(get-long-type out-type
)))
53 (t `(* ,(coerce 1 (get-long-type out-type
)) x
))))
58 ;; create downconversions from complex types like
59 ;; cdf df #'realpart realpart
60 (def-comps (in-type out-type functions
&optional
(fun t
))
61 (loop for func in functions collect
65 (:floor
`#'(lambda (x) (floor (funcall #',func x
))))
68 ;; an element of spec looks like this: (ub8 sf #'(lambda(x) (* 1s0 x))
69 ;; mul) the first two cols define input and output types, then
70 ;; comes a function that does this conversion followed by a short
71 ;; name describing the function. this name is attached to the
73 (let ((specs `(;; upconvert from ub8 into sf and similar
91 ;; upconvert complex to complex
94 ;; downconvert from double into single
95 ,(def 'df
'sf
:coerce
)
96 ,(def 'cdf
'csf
:coerce
)
98 ;; downconvert from float into bytes
99 ,(def 'sf
'ub8
:floor
)
100 ,(def 'df
'ub8
:floor
)
101 ,(def 'sf
'fix
:floor
)
102 ,(def 'df
'fix
:floor
)
104 ;; convert from complex into real
105 ,@(def-comps 'csf
'sf
'(realpart imagpart abs phase
))
106 ,@(def-comps 'cdf
'df
'(realpart imagpart abs phase
))
108 ;; complex into real and conversion into fixed
109 ,@(def-comps 'csf
'ub8
'(realpart imagpart abs phase
) :floor
)
110 ,@(def-comps 'cdf
'ub8
'(realpart imagpart abs phase
) :floor
)
113 (loop for rank in
'(1 2 3) do
114 (loop for spec in specs do
115 (destructuring-bind (in out fun name
)
117 (push `(def-convert-rank-type-out_type-func-short_func
118 ,rank
,in
,out
,fun
,name
)
122 (def-convert-functions)
125 (convert-3-cdf/ub8-realpart
126 (make-array (list 3 3 3) :element-type
'(complex double-float
)))
129 (convert-3-csf/cdf-mul
130 (make-array (list 3 3 3) :element-type
'(complex single-float
)))
133 ;; converting complex into real with some function and converting into
134 ;; out_type, the name of the functions will be like:
135 ;; normalize-3-cdf/ub8-realpart. the function is evaluated into an
136 ;; intermediate real array (either double or float depending on the
137 ;; input type) and then normalized into the result. float results are
138 ;; in 0..1 and ub8 results in 0..255.
139 (def-generator (normalize-complex (rank type out_type func short_func
))
140 (let ((long-out-type (get-long-type out_type
))
141 ;; override the name that is constructed by def-generator
142 (name (format-symbol "normalize-~a-~a/~a-~a"
143 rank type out_type short_func
))
144 (intermed-type (ecase type
146 (csf 'single-float
))))
147 (store-new-function name
)
149 (declare ((simple-array ,long-type
,rank
) a
)
150 (values (simple-array ,long-out-type
,rank
) &optional
))
151 (let* ((result (make-array (array-dimensions a
)
152 :element-type
',long-out-type
))
153 (result1 (sb-ext:array-storage-vector result
))
154 (a1 (sb-ext:array-storage-vector a
))
157 (make-array n
:element-type
',intermed-type
)))
159 (setf (aref intermediate1 i
) (funcall ,func
(aref a1 i
))))
160 (let* ((ma (reduce #'max intermediate1
))
161 (mi (reduce #'min intermediate1
))
163 (coerce 0 ',intermed-type
)
166 (let ((v (* s
(- (aref intermediate1 i
) mi
))))
167 (setf (aref result1 i
) ,(if (eq 'ub8 out_type
)
169 `(* (coerce 1 ',long-out-type
) v
)))))
173 (def-normalize-complex-rank-type-out_type-func-short_func
174 1 csf ub8
#'realpart realpart
)
176 (defmacro def-normalize-complex-functions
(ranks out-types funcs
)
178 (loop for rank in ranks do
179 (loop for type in
'(csf cdf
) do
180 (loop for otype in out-types do
181 (loop for func in funcs do
182 (push `(def-normalize-complex-rank-type-out_type-func-short_func ,rank
,type
,otype
#',func
,func
)
186 (def-normalize-complex-functions
187 (1 2 3) (ub8 sf df
) (realpart imagpart phase abs
))
190 (normalize-1-csf/ub8-realpart
191 (make-array 3 :element-type
'(complex single-float
)
192 :initial-contents
'(#C
(1s0 0s0
) #C
(2s0 0s0
) #C
(3s0 0s0
))))
195 (normalize-1-csf/df-phase
196 (make-array 3 :element-type
'(complex single-float
)
197 :initial-contents
'(#C
(1s0 .2s0
) #C
(2s0 1s0
) #C
(3s0 0s0
))))
199 ;; normalize real arrays, name like: normalize-2-sf/ub8
200 (def-generator (normalize (rank type out_type
))
201 (let ((long-out-type (get-long-type out_type
))
202 ;; override the name that is constructed by def-generator
203 (name (format-symbol "normalize-~a-~a/~a"
204 rank type out_type
)))
205 (store-new-function name
)
207 (declare ((simple-array ,long-type
,rank
) a
)
208 (values (simple-array ,long-out-type
,rank
) &optional
))
209 (let* ((result (make-array (array-dimensions a
)
210 :element-type
',long-out-type
))
211 (result1 (sb-ext:array-storage-vector result
))
212 (a1 (sb-ext:array-storage-vector a
))
214 (ma (reduce #'max a1
))
215 (mi (reduce #'min a1
))
217 (coerce 0 ',(get-long-type type
))
220 (let ((v (* s
(- (aref a1 i
) mi
))))
221 (setf (aref result1 i
) ,(if (eq 'ub8 out_type
)
223 `(* (coerce 1 ',long-out-type
) v
)))))
226 (def-normalize-rank-type-out_type 1 df ub8
)
228 (normalize-1-df/ub8
(make-array 3 :element-type
'double-float
229 :initial-contents
'(1d0 2d0
3d0
)))
231 (defmacro def-normalize-functions
(ranks in-types out-types
)
233 (loop for rank in ranks do
234 (loop for type in in-types do
235 (loop for otype in out-types do
236 (push `(def-normalize-rank-type-out_type ,rank
,type
,otype
)
240 (def-normalize-functions (1 2 3) (ub8 sf df
) (ub8 sf df
))
243 (normalize-1-sf/sf
(make-array 3 :element-type
'single-float
244 :initial-contents
'(1s0 2s0
3s0
)))
246 (normalize-1-sf/ub8
(make-array 3 :element-type
'single-float
247 :initial-contents
'(1s0 2s0
3s0
)))
249 (normalize-1-ub8/sf
(make-array 3 :element-type
'(unsigned-byte 8)
250 :initial-contents
'(1 2 3)))
252 (normalize-1-ub8/ub8
(make-array 3 :element-type
'(unsigned-byte 8)
253 :initial-contents
'(1 2 3)))
255 #+nil
;; find the names of all the functions that were defined by the
256 ;; above macros, for exporting
257 ;; 2010-08-14 I don't think I need this anymore
259 (with-package-iterator (next-symbol *package
* :internal
)
260 (loop (multiple-value-bind (more? symbol
)
265 (loop for s in
(delete-if-not #'(lambda (x)
266 (let* ((pat "CONVERT"
270 (when (< lpat
(length x
))
274 (mapcar #'(lambda (x)
275 (format nil
"~a" x
)) res
))
276 do
(format t
"#:~a~%" (string-downcase s
))))