ivan@78
|
1 /*
|
ivan@78
|
2 File Name: mirdwt.c
|
ivan@78
|
3 Last Modification Date: %G% %U%
|
ivan@78
|
4 Current Version: %M% %I%
|
ivan@78
|
5 File Creation Date: Wed Oct 12 08:44:43 1994
|
ivan@78
|
6 Author: Markus Lang <lang@jazz.rice.edu>
|
ivan@78
|
7
|
ivan@78
|
8 Copyright: All software, documentation, and related files in this distribution
|
ivan@78
|
9 are Copyright (c) 1994 Rice University
|
ivan@78
|
10
|
ivan@78
|
11 Permission is granted for use and non-profit distribution providing that this
|
ivan@78
|
12 notice be clearly maintained. The right to distribute any portion for profit
|
ivan@78
|
13 or as part of any commercial product is specifically reserved for the author.
|
ivan@78
|
14
|
ivan@78
|
15 Change History: Fixed code such that the result has the same dimension as the
|
ivan@78
|
16 input for 1D problems. Also, added some standard error checking.
|
ivan@78
|
17 Jan Erik Odegard <odegard@ece.rice.edu> Wed Jun 14 1995
|
ivan@78
|
18
|
ivan@78
|
19 */
|
ivan@78
|
20
|
ivan@78
|
21 #include <math.h>
|
ivan@78
|
22 /*#include <malloc.h>*/
|
ivan@78
|
23 #include <stdio.h>
|
ivan@78
|
24 #include "mex.h"
|
ivan@78
|
25 #include "matrix.h"
|
ivan@78
|
26 #if !defined(_WIN32) && !defined(_WIN64)
|
ivan@78
|
27 #include <inttypes.h>
|
ivan@78
|
28 #endif
|
ivan@78
|
29 #define max(A,B) (A > B ? A : B)
|
ivan@78
|
30 #define min(A,B) (A < B ? A : B)
|
ivan@78
|
31 #define even(x) ((x & 1) ? 0 : 1)
|
ivan@78
|
32 #define isint(x) ((x - floor(x)) > 0.0 ? 0 : 1)
|
ivan@78
|
33
|
ivan@78
|
34
|
ivan@78
|
35 void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
|
ivan@78
|
36
|
ivan@78
|
37 {
|
ivan@78
|
38 double *x, *h, *yl, *yh, *Lf, *Lr;
|
ivan@78
|
39 intptr_t m, n, mh, nh, h_col, h_row, lh, L, i, po2, j;
|
ivan@78
|
40 double mtest, ntest;
|
ivan@78
|
41
|
ivan@78
|
42 /* check for correct # of input variables */
|
ivan@78
|
43 if (nrhs>4){
|
ivan@78
|
44 mexErrMsgTxt("There are at most 4 input parameters allowed!");
|
ivan@78
|
45 return;
|
ivan@78
|
46 }
|
ivan@78
|
47 if (nrhs<3){
|
ivan@78
|
48 mexErrMsgTxt("There are at least 3 input parameters required!");
|
ivan@78
|
49 return;
|
ivan@78
|
50 }
|
ivan@78
|
51 yl = mxGetPr(prhs[0]);
|
ivan@78
|
52 n = mxGetN(prhs[0]);
|
ivan@78
|
53 m = mxGetM(prhs[0]);
|
ivan@78
|
54 yh = mxGetPr(prhs[1]);
|
ivan@78
|
55 nh = mxGetN(prhs[1]);
|
ivan@78
|
56 mh = mxGetM(prhs[1]);
|
ivan@78
|
57 h = mxGetPr(prhs[2]);
|
ivan@78
|
58 h_col = mxGetN(prhs[2]);
|
ivan@78
|
59 h_row = mxGetM(prhs[2]);
|
ivan@78
|
60 if (h_col>h_row)
|
ivan@78
|
61 lh = h_col;
|
ivan@78
|
62 else
|
ivan@78
|
63 lh = h_row;
|
ivan@78
|
64 if (nrhs == 4){
|
ivan@78
|
65 L = (intptr_t) *mxGetPr(prhs[3]);
|
ivan@78
|
66 if (L < 0)
|
ivan@78
|
67 mexErrMsgTxt("The number of levels, L, must be a non-negative integer");
|
ivan@78
|
68 }
|
ivan@78
|
69 else /* Estimate L */ {
|
ivan@78
|
70 i=n;j=0;
|
ivan@78
|
71 while (even(i)){
|
ivan@78
|
72 i=(i>>1);
|
ivan@78
|
73 j++;
|
ivan@78
|
74 }
|
ivan@78
|
75 L=m;i=0;
|
ivan@78
|
76 while (even(L)){
|
ivan@78
|
77 L=(L>>1);
|
ivan@78
|
78 i++;
|
ivan@78
|
79 }
|
ivan@78
|
80 if(min(m,n) == 1)
|
ivan@78
|
81 L = max(i,j);
|
ivan@78
|
82 else
|
ivan@78
|
83 L = min(i,j);
|
ivan@78
|
84 if (L==0){
|
ivan@78
|
85 mexErrMsgTxt("Maximum number of levels is zero; no decomposition can be performed!");
|
ivan@78
|
86 return;
|
ivan@78
|
87 }
|
ivan@78
|
88 }
|
ivan@78
|
89 /* check for consistency of rows and columns of yl, yh */
|
ivan@78
|
90 if (min(m,n) > 1){
|
ivan@78
|
91 if((m != mh) | (3*n*L != nh)){
|
ivan@78
|
92 mexErrMsgTxt("Dimensions of first two input matrices not consistent!");
|
ivan@78
|
93 return;
|
ivan@78
|
94 }
|
ivan@78
|
95 }
|
ivan@78
|
96 else{
|
ivan@78
|
97 if((m != mh) | (n*L != nh)){
|
ivan@78
|
98 mexErrMsgTxt("Dimensions of first two input vectors not consistent!");{
|
ivan@78
|
99 return;
|
ivan@78
|
100 }
|
ivan@78
|
101 }
|
ivan@78
|
102 }
|
ivan@78
|
103 /* Check the ROW dimension of input */
|
ivan@78
|
104 if(m > 1){
|
ivan@78
|
105 mtest = (double) m/pow(2.0, (double) L);
|
ivan@78
|
106 if (!isint(mtest))
|
ivan@78
|
107 mexErrMsgTxt("The matrix row dimension must be of size m*2^(L)");
|
ivan@78
|
108 }
|
ivan@78
|
109 /* Check the COLUMN dimension of input */
|
ivan@78
|
110 if(n > 1){
|
ivan@78
|
111 ntest = (double) n/pow(2.0, (double) L);
|
ivan@78
|
112 if (!isint(ntest))
|
ivan@78
|
113 mexErrMsgTxt("The matrix column dimension must be of size n*2^(L)");
|
ivan@78
|
114 }
|
ivan@78
|
115 plhs[0] = mxCreateDoubleMatrix(m,n,mxREAL);
|
ivan@78
|
116 x = mxGetPr(plhs[0]);
|
ivan@78
|
117 plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL);
|
ivan@78
|
118 Lr = mxGetPr(plhs[1]);
|
ivan@78
|
119 *Lr = L;
|
ivan@78
|
120 MIRDWT(x, m, n, h, lh, L, yl, yh);
|
ivan@78
|
121 }
|
ivan@78
|
122 #define mat(a, i, j) (*(a + (m*(j)+i))) /* macro for matrix indices */
|
ivan@78
|
123
|
ivan@78
|
124 #ifdef __STDC__
|
ivan@78
|
125 MIRDWT(double *x, intptr_t m, intptr_t n, double *h, intptr_t lh, intptr_t L,
|
ivan@78
|
126 double *yl, double *yh)
|
ivan@78
|
127 #else
|
ivan@78
|
128 MIRDWT(x, m, n, h, lh, L, yl, yh)
|
ivan@78
|
129 double *x, *h, *yl, *yh;
|
ivan@78
|
130 intptr_t m, n, lh, L;
|
ivan@78
|
131 #endif
|
ivan@78
|
132 {
|
ivan@78
|
133 double *g0, *g1, *ydummyll, *ydummylh, *ydummyhl;
|
ivan@78
|
134 double *ydummyhh, *xdummyl , *xdummyh, *xh;
|
ivan@78
|
135 intptr_t i, j;
|
ivan@78
|
136 intptr_t actual_L, actual_m, actual_n, c_o_a, ir, n_c, n_cb, n_c_o, lhm1;
|
ivan@78
|
137 intptr_t ic, n_r, n_rb, n_r_o, c_o_a_p2n, sample_f;
|
ivan@78
|
138 xh = (double *)(intptr_t)mxCalloc(m*n,sizeof(double));
|
ivan@78
|
139 xdummyl = (double *)(intptr_t)mxCalloc(max(m,n),sizeof(double));
|
ivan@78
|
140 xdummyh = (double *)(intptr_t)mxCalloc(max(m,n),sizeof(double));
|
ivan@78
|
141 ydummyll = (double *)(intptr_t)mxCalloc(max(m,n)+lh-1,sizeof(double));
|
ivan@78
|
142 ydummylh = (double *)(intptr_t)mxCalloc(max(m,n)+lh-1,sizeof(double));
|
ivan@78
|
143 ydummyhl = (double *)(intptr_t)mxCalloc(max(m,n)+lh-1,sizeof(double));
|
ivan@78
|
144 ydummyhh = (double *)(intptr_t)mxCalloc(max(m,n)+lh-1,sizeof(double));
|
ivan@78
|
145 g0 = (double *)(intptr_t)mxCalloc(lh,sizeof(double));
|
ivan@78
|
146 g1 = (double *)(intptr_t)mxCalloc(lh,sizeof(double));
|
ivan@78
|
147
|
ivan@78
|
148 if (n==1){
|
ivan@78
|
149 n = m;
|
ivan@78
|
150 m = 1;
|
ivan@78
|
151 }
|
ivan@78
|
152 /* analysis lowpass and highpass */
|
ivan@78
|
153 for (i=0; i<lh; i++){
|
ivan@78
|
154 g0[i] = h[i]/2;
|
ivan@78
|
155 g1[i] = h[lh-i-1]/2;
|
ivan@78
|
156 }
|
ivan@78
|
157 for (i=1; i<=lh; i+=2)
|
ivan@78
|
158 g1[i] = -g1[i];
|
ivan@78
|
159
|
ivan@78
|
160 lhm1 = lh - 1;
|
ivan@78
|
161 /* 2^L */
|
ivan@78
|
162 sample_f = 1;
|
ivan@78
|
163 for (i=1; i<L; i++)
|
ivan@78
|
164 sample_f = sample_f*2;
|
ivan@78
|
165 actual_m = m/sample_f;
|
ivan@78
|
166 actual_n = n/sample_f;
|
ivan@78
|
167 /* restore yl in x */
|
ivan@78
|
168 for (i=0;i<m*n;i++)
|
ivan@78
|
169 x[i] = yl[i];
|
ivan@78
|
170
|
ivan@78
|
171 /* main loop */
|
ivan@78
|
172 for (actual_L=L; actual_L >= 1; actual_L--){
|
ivan@78
|
173 /* actual (level dependent) column offset */
|
ivan@78
|
174 if (m==1)
|
ivan@78
|
175 c_o_a = n*(actual_L-1);
|
ivan@78
|
176 else
|
ivan@78
|
177 c_o_a = 3*n*(actual_L-1);
|
ivan@78
|
178 c_o_a_p2n = c_o_a + 2*n;
|
ivan@78
|
179
|
ivan@78
|
180 /* go by columns in case of a 2D signal*/
|
ivan@78
|
181 if (m>1){
|
ivan@78
|
182 n_rb = m/actual_m; /* # of row blocks per column */
|
ivan@78
|
183 for (ic=0; ic<n; ic++){ /* loop over column */
|
ivan@78
|
184 for (n_r=0; n_r<n_rb; n_r++){ /* loop within one column */
|
ivan@78
|
185 /* store in dummy variables */
|
ivan@78
|
186 ir = -sample_f + n_r;
|
ivan@78
|
187 for (i=0; i<actual_m; i++){
|
ivan@78
|
188 ir = ir + sample_f;
|
ivan@78
|
189 ydummyll[i+lhm1] = mat(x, ir, ic);
|
ivan@78
|
190 ydummylh[i+lhm1] = mat(yh, ir, c_o_a+ic);
|
ivan@78
|
191 ydummyhl[i+lhm1] = mat(yh, ir,c_o_a+n+ic);
|
ivan@78
|
192 ydummyhh[i+lhm1] = mat(yh, ir, c_o_a_p2n+ic);
|
ivan@78
|
193 }
|
ivan@78
|
194 /* perform filtering and adding: first LL/LH, then HL/HH */
|
ivan@78
|
195 bpconv(xdummyl, actual_m, g0, g1, lh, ydummyll, ydummylh);
|
ivan@78
|
196 bpconv(xdummyh, actual_m, g0, g1, lh, ydummyhl, ydummyhh);
|
ivan@78
|
197 /* store dummy variables in matrices */
|
ivan@78
|
198 ir = -sample_f + n_r;
|
ivan@78
|
199 for (i=0; i<actual_m; i++){
|
ivan@78
|
200 ir = ir + sample_f;
|
ivan@78
|
201 mat(x, ir, ic) = xdummyl[i];
|
ivan@78
|
202 mat(xh, ir, ic) = xdummyh[i];
|
ivan@78
|
203 }
|
ivan@78
|
204 }
|
ivan@78
|
205 }
|
ivan@78
|
206 }
|
ivan@78
|
207
|
ivan@78
|
208 /* go by rows */
|
ivan@78
|
209 n_cb = n/actual_n; /* # of column blocks per row */
|
ivan@78
|
210 for (ir=0; ir<m; ir++){ /* loop over rows */
|
ivan@78
|
211 for (n_c=0; n_c<n_cb; n_c++){ /* loop within one row */
|
ivan@78
|
212 /* store in dummy variable */
|
ivan@78
|
213 ic = -sample_f + n_c;
|
ivan@78
|
214 for (i=0; i<actual_n; i++){
|
ivan@78
|
215 ic = ic + sample_f;
|
ivan@78
|
216 ydummyll[i+lhm1] = mat(x, ir, ic);
|
ivan@78
|
217 if (m>1)
|
ivan@78
|
218 ydummyhh[i+lhm1] = mat(xh, ir, ic);
|
ivan@78
|
219 else
|
ivan@78
|
220 ydummyhh[i+lhm1] = mat(yh, ir, c_o_a+ic);
|
ivan@78
|
221 }
|
ivan@78
|
222 /* perform filtering lowpass/highpass */
|
ivan@78
|
223 bpconv(xdummyl, actual_n, g0, g1, lh, ydummyll, ydummyhh);
|
ivan@78
|
224 /* restore dummy variables in matrices */
|
ivan@78
|
225 ic = -sample_f + n_c;
|
ivan@78
|
226 for (i=0; i<actual_n; i++){
|
ivan@78
|
227 ic = ic + sample_f;
|
ivan@78
|
228 mat(x, ir, ic) = xdummyl[i];
|
ivan@78
|
229 }
|
ivan@78
|
230 }
|
ivan@78
|
231 }
|
ivan@78
|
232 sample_f = sample_f/2;
|
ivan@78
|
233 actual_m = actual_m*2;
|
ivan@78
|
234 actual_n = actual_n*2;
|
ivan@78
|
235 }
|
ivan@78
|
236 }
|
ivan@78
|
237
|
ivan@78
|
238 #ifdef __STDC__
|
ivan@78
|
239 bpconv(double *x_out, intptr_t lx, double *g0, double *g1, intptr_t lh,
|
ivan@78
|
240 double *x_inl, double *x_inh)
|
ivan@78
|
241 #else
|
ivan@78
|
242 bpconv(x_out, lx, g0, g1, lh, x_inl, x_inh)
|
ivan@78
|
243 double *x_inl, *x_inh, *g0, *g1, *x_out;
|
ivan@78
|
244 intptr_t lx, lh;
|
ivan@78
|
245 #endif
|
ivan@78
|
246 {
|
ivan@78
|
247 intptr_t i, j;
|
ivan@78
|
248 double x0;
|
ivan@78
|
249
|
ivan@78
|
250 for (i=lh-2; i > -1; i--){
|
ivan@78
|
251 x_inl[i] = x_inl[lx+i];
|
ivan@78
|
252 x_inh[i] = x_inh[lx+i];
|
ivan@78
|
253 }
|
ivan@78
|
254 for (i=0; i<lx; i++){
|
ivan@78
|
255 x0 = 0;
|
ivan@78
|
256 for (j=0; j<lh; j++)
|
ivan@78
|
257 x0 = x0 + x_inl[j+i]*g0[lh-1-j] +
|
ivan@78
|
258 x_inh[j+i]*g1[lh-1-j];
|
ivan@78
|
259 x_out[i] = x0;
|
ivan@78
|
260 }
|
ivan@78
|
261 }
|