Mercurial > hg > smallbox
comparison solvers/SMALL_ompGabor/ompcore.c @ 140:31d2864dfdd4 ivand_dev
Audio Impainting additional constraints with cvx added
author | Ivan Damnjanovic lnx <ivan.damnjanovic@eecs.qmul.ac.uk> |
---|---|
date | Mon, 25 Jul 2011 17:27:05 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
139:4bd6856a7128 | 140:31d2864dfdd4 |
---|---|
1 /************************************************************************** | |
2 * | |
3 * File name: ompcore.c | |
4 * | |
5 * Ron Rubinstein | |
6 * Computer Science Department | |
7 * Technion, Haifa 32000 Israel | |
8 * ronrubin@cs | |
9 * | |
10 * Last Updated: 25.8.2009 | |
11 * | |
12 *************************************************************************/ | |
13 | |
14 | |
15 #include "ompcore.h" | |
16 #include "omputils.h" | |
17 #include "ompprof.h" | |
18 #include "myblas.h" | |
19 #include <math.h> | |
20 #include <string.h> | |
21 | |
22 | |
23 | |
24 /****************************************************************************** | |
25 * * | |
26 * Batch-OMP Implementation * | |
27 * * | |
28 ******************************************************************************/ | |
29 | |
30 mxArray* ompcore(double D[], double x[], double DtX[], double XtX[], double G[], mwSize n, mwSize m, mwSize L, | |
31 int T, double eps, int gamma_mode, int profile, double msg_delta, int erroromp) | |
32 { | |
33 | |
34 profdata pd; | |
35 mxArray *Gamma; | |
36 mwIndex i, j, signum, pos, *ind, *gammaIr, *gammaJc, gamma_count; | |
37 mwSize allocated_coefs, allocated_cols; | |
38 int DtX_specified, XtX_specified, batchomp, standardomp, *selected_atoms; | |
39 double *alpha, *r, *Lchol, *c, *Gsub, *Dsub, sum, *gammaPr, *tempvec1, *tempvec2; | |
40 double eps2, resnorm, delta, deltaprev, secs_remain; | |
41 int mins_remain, hrs_remain; | |
42 clock_t lastprint_time, starttime; | |
43 | |
44 | |
45 | |
46 /*** status flags ***/ | |
47 | |
48 DtX_specified = (DtX!=0); /* indicates whether D'*x was provided */ | |
49 XtX_specified = (XtX!=0); /* indicates whether sum(x.*x) was provided */ | |
50 | |
51 standardomp = (G==0); /* batch-omp or standard omp are selected depending on availability of G */ | |
52 batchomp = !standardomp; | |
53 | |
54 | |
55 | |
56 /*** allocate output matrix ***/ | |
57 | |
58 | |
59 if (gamma_mode == FULL_GAMMA) { | |
60 | |
61 /* allocate full matrix of size m X L */ | |
62 | |
63 Gamma = mxCreateDoubleMatrix(m, L, mxREAL); | |
64 gammaPr = mxGetPr(Gamma); | |
65 gammaIr = 0; | |
66 gammaJc = 0; | |
67 } | |
68 else { | |
69 | |
70 /* allocate sparse matrix with room for allocated_coefs nonzeros */ | |
71 | |
72 /* for error-omp, begin with L*sqrt(n)/2 allocated nonzeros, otherwise allocate L*T nonzeros */ | |
73 allocated_coefs = erroromp ? (mwSize)(ceil(L*sqrt((double)n)/2.0) + 1.01) : L*T; | |
74 Gamma = mxCreateSparse(m, L, allocated_coefs, mxREAL); | |
75 gammaPr = mxGetPr(Gamma); | |
76 gammaIr = mxGetIr(Gamma); | |
77 gammaJc = mxGetJc(Gamma); | |
78 gamma_count = 0; | |
79 gammaJc[0] = 0; | |
80 } | |
81 | |
82 | |
83 /*** helper arrays ***/ | |
84 | |
85 alpha = (double*)mxMalloc(m*sizeof(double)); /* contains D'*residual */ | |
86 ind = (mwIndex*)mxMalloc(n*sizeof(mwIndex)); /* indices of selected atoms */ | |
87 selected_atoms = (int*)mxMalloc(m*sizeof(int)); /* binary array with 1's for selected atoms */ | |
88 c = (double*)mxMalloc(n*sizeof(double)); /* orthogonal projection result */ | |
89 | |
90 /* current number of columns in Dsub / Gsub / Lchol */ | |
91 allocated_cols = erroromp ? (mwSize)(ceil(sqrt((double)n)/2.0) + 1.01) : T; | |
92 | |
93 /* Cholesky decomposition of D_I'*D_I */ | |
94 Lchol = (double*)mxMalloc(n*allocated_cols*sizeof(double)); | |
95 | |
96 /* temporary vectors for various computations */ | |
97 tempvec1 = (double*)mxMalloc(m*sizeof(double)); | |
98 tempvec2 = (double*)mxMalloc(m*sizeof(double)); | |
99 | |
100 if (batchomp) { | |
101 /* matrix containing G(:,ind) - the columns of G corresponding to the selected atoms, in order of selection */ | |
102 Gsub = (double*)mxMalloc(m*allocated_cols*sizeof(double)); | |
103 } | |
104 else { | |
105 /* matrix containing D(:,ind) - the selected atoms from D, in order of selection */ | |
106 Dsub = (double*)mxMalloc(n*allocated_cols*sizeof(double)); | |
107 | |
108 /* stores the residual */ | |
109 r = (double*)mxMalloc(n*sizeof(double)); | |
110 } | |
111 | |
112 if (!DtX_specified) { | |
113 /* contains D'*x for the current signal */ | |
114 DtX = (double*)mxMalloc(m*sizeof(double)); | |
115 } | |
116 | |
117 | |
118 | |
119 /*** initializations for error omp ***/ | |
120 | |
121 if (erroromp) { | |
122 eps2 = eps*eps; /* compute eps^2 */ | |
123 if (T<0 || T>n) { /* unspecified max atom num - set max atoms to n */ | |
124 T = n; | |
125 } | |
126 } | |
127 | |
128 | |
129 | |
130 /*** initialize timers ***/ | |
131 | |
132 initprofdata(&pd); /* initialize profiling counters */ | |
133 starttime = clock(); /* record starting time for eta computations */ | |
134 lastprint_time = starttime; /* time of last status display */ | |
135 | |
136 | |
137 | |
138 /********************** perform omp for each signal **********************/ | |
139 | |
140 | |
141 | |
142 for (signum=0; signum<L; ++signum) { | |
143 | |
144 | |
145 /* initialize residual norm and deltaprev for error-omp */ | |
146 | |
147 if (erroromp) { | |
148 if (XtX_specified) { | |
149 resnorm = XtX[signum]; | |
150 } | |
151 else { | |
152 resnorm = dotprod(x+n*signum, x+n*signum, n); | |
153 addproftime(&pd, XtX_TIME); | |
154 } | |
155 deltaprev = 0; /* delta tracks the value of gamma'*G*gamma */ | |
156 } | |
157 else { | |
158 /* ignore residual norm stopping criterion */ | |
159 eps2 = 0; | |
160 resnorm = 1; | |
161 } | |
162 | |
163 | |
164 if (resnorm>eps2 && T>0) { | |
165 | |
166 /* compute DtX */ | |
167 | |
168 if (!DtX_specified) { | |
169 matT_vec(1, D, x+n*signum, DtX, n, m); | |
170 addproftime(&pd, DtX_TIME); | |
171 } | |
172 | |
173 | |
174 /* initialize alpha := DtX */ | |
175 | |
176 memcpy(alpha, DtX + m*signum*DtX_specified, m*sizeof(double)); | |
177 | |
178 | |
179 /* mark all atoms as unselected */ | |
180 | |
181 for (i=0; i<m; ++i) { | |
182 selected_atoms[i] = 0; | |
183 } | |
184 | |
185 } | |
186 | |
187 | |
188 /* main loop */ | |
189 | |
190 i=0; | |
191 while (resnorm>eps2 && i<T) { | |
192 | |
193 /* index of next atom */ | |
194 | |
195 pos = maxabs(alpha, m); | |
196 addproftime(&pd, MAXABS_TIME); | |
197 | |
198 | |
199 /* stop criterion: selected same atom twice, or inner product too small */ | |
200 | |
201 if (selected_atoms[pos] || alpha[pos]*alpha[pos]<1e-14) { | |
202 break; | |
203 } | |
204 | |
205 | |
206 /* mark selected atom */ | |
207 | |
208 ind[i] = pos; | |
209 selected_atoms[pos] = 1; | |
210 | |
211 | |
212 /* matrix reallocation */ | |
213 | |
214 if (erroromp && i>=allocated_cols) { | |
215 | |
216 allocated_cols = (mwSize)(ceil(allocated_cols*MAT_INC_FACTOR) + 1.01); | |
217 | |
218 Lchol = (double*)mxRealloc(Lchol,n*allocated_cols*sizeof(double)); | |
219 | |
220 batchomp ? (Gsub = (double*)mxRealloc(Gsub,m*allocated_cols*sizeof(double))) : | |
221 (Dsub = (double*)mxRealloc(Dsub,n*allocated_cols*sizeof(double))) ; | |
222 } | |
223 | |
224 | |
225 /* append column to Gsub or Dsub */ | |
226 | |
227 if (batchomp) { | |
228 memcpy(Gsub+i*m, G+pos*m, m*sizeof(double)); | |
229 } | |
230 else { | |
231 memcpy(Dsub+i*n, D+pos*n, n*sizeof(double)); | |
232 } | |
233 | |
234 | |
235 /*** Cholesky update ***/ | |
236 | |
237 if (i==0) { | |
238 *Lchol = 1; | |
239 } | |
240 else { | |
241 | |
242 /* incremental Cholesky decomposition: compute next row of Lchol */ | |
243 | |
244 if (standardomp) { | |
245 matT_vec(1, Dsub, D+n*pos, tempvec1, n, i); /* compute tempvec1 := Dsub'*d where d is new atom */ | |
246 addproftime(&pd, DtD_TIME); | |
247 } | |
248 else { | |
249 vec_assign(tempvec1, Gsub+i*m, ind, i); /* extract tempvec1 := Gsub(ind,i) */ | |
250 } | |
251 backsubst('L', Lchol, tempvec1, tempvec2, n, i); /* compute tempvec2 = Lchol \ tempvec1 */ | |
252 for (j=0; j<i; ++j) { /* write tempvec2 to end of Lchol */ | |
253 Lchol[j*n+i] = tempvec2[j]; | |
254 } | |
255 | |
256 /* compute Lchol(i,i) */ | |
257 sum = 0; | |
258 for (j=0; j<i; ++j) { /* compute sum of squares of last row without Lchol(i,i) */ | |
259 sum += SQR(Lchol[j*n+i]); | |
260 } | |
261 if ( (1-sum) <= 1e-14 ) { /* Lchol(i,i) is zero => selected atoms are dependent */ | |
262 break; | |
263 } | |
264 Lchol[i*n+i] = sqrt(1-sum); | |
265 } | |
266 | |
267 addproftime(&pd, LCHOL_TIME); | |
268 | |
269 i++; | |
270 | |
271 | |
272 /* perform orthogonal projection and compute sparse coefficients */ | |
273 | |
274 vec_assign(tempvec1, DtX + m*signum*DtX_specified, ind, i); /* extract tempvec1 = DtX(ind) */ | |
275 cholsolve('L', Lchol, tempvec1, c, n, i); /* solve LL'c = tempvec1 for c */ | |
276 addproftime(&pd, COMPCOEF_TIME); | |
277 | |
278 | |
279 /* update alpha = D'*residual */ | |
280 | |
281 if (standardomp) { | |
282 mat_vec(-1, Dsub, c, r, n, i); /* compute r := -Dsub*c */ | |
283 vec_sum(1, x+n*signum, r, n); /* compute r := x+r */ | |
284 | |
285 | |
286 /*memcpy(r, x+n*signum, n*sizeof(double)); /* assign r := x */ | |
287 /*mat_vec1(-1, Dsub, c, 1, r, n, i); /* compute r := r-Dsub*c */ | |
288 | |
289 addproftime(&pd, COMPRES_TIME); | |
290 matT_vec(1, D, r, alpha, n, m); /* compute alpha := D'*r */ | |
291 addproftime(&pd, DtR_TIME); | |
292 | |
293 /* update residual norm */ | |
294 if (erroromp) { | |
295 resnorm = dotprod(r, r, n); | |
296 addproftime(&pd, UPDATE_RESNORM_TIME); | |
297 } | |
298 } | |
299 else { | |
300 mat_vec(1, Gsub, c, tempvec1, m, i); /* compute tempvec1 := Gsub*c */ | |
301 memcpy(alpha, DtX + m*signum*DtX_specified, m*sizeof(double)); /* set alpha = D'*x */ | |
302 vec_sum(-1, tempvec1, alpha, m); /* compute alpha := alpha - tempvec1 */ | |
303 addproftime(&pd, UPDATE_DtR_TIME); | |
304 | |
305 /* update residual norm */ | |
306 if (erroromp) { | |
307 vec_assign(tempvec2, tempvec1, ind, i); /* assign tempvec2 := tempvec1(ind) */ | |
308 delta = dotprod(c,tempvec2,i); /* compute c'*tempvec2 */ | |
309 resnorm = resnorm - delta + deltaprev; /* residual norm update */ | |
310 deltaprev = delta; | |
311 addproftime(&pd, UPDATE_RESNORM_TIME); | |
312 } | |
313 } | |
314 } | |
315 | |
316 | |
317 /*** generate output vector gamma ***/ | |
318 | |
319 if (gamma_mode == FULL_GAMMA) { /* write the coefs in c to their correct positions in gamma */ | |
320 for (j=0; j<i; ++j) { | |
321 gammaPr[m*signum + ind[j]] = c[j]; | |
322 } | |
323 } | |
324 else { | |
325 /* sort the coefs by index before writing them to gamma */ | |
326 quicksort(ind,c,i); | |
327 addproftime(&pd, INDEXSORT_TIME); | |
328 | |
329 /* gamma is full - reallocate */ | |
330 if (gamma_count+i >= allocated_coefs) { | |
331 | |
332 while(gamma_count+i >= allocated_coefs) { | |
333 allocated_coefs = (mwSize)(ceil(GAMMA_INC_FACTOR*allocated_coefs) + 1.01); | |
334 } | |
335 | |
336 mxSetNzmax(Gamma, allocated_coefs); | |
337 mxSetPr(Gamma, mxRealloc(gammaPr, allocated_coefs*sizeof(double))); | |
338 mxSetIr(Gamma, mxRealloc(gammaIr, allocated_coefs*sizeof(mwIndex))); | |
339 | |
340 gammaPr = mxGetPr(Gamma); | |
341 gammaIr = mxGetIr(Gamma); | |
342 } | |
343 | |
344 /* append coefs to gamma and update the indices */ | |
345 for (j=0; j<i; ++j) { | |
346 gammaPr[gamma_count] = c[j]; | |
347 gammaIr[gamma_count] = ind[j]; | |
348 gamma_count++; | |
349 } | |
350 gammaJc[signum+1] = gammaJc[signum] + i; | |
351 } | |
352 | |
353 | |
354 | |
355 /*** display status messages ***/ | |
356 | |
357 if (msg_delta>0 && (clock()-lastprint_time)/(double)CLOCKS_PER_SEC >= msg_delta) | |
358 { | |
359 lastprint_time = clock(); | |
360 | |
361 /* estimated remainig time */ | |
362 secs2hms( ((L-signum-1)/(double)(signum+1)) * ((lastprint_time-starttime)/(double)CLOCKS_PER_SEC) , | |
363 &hrs_remain, &mins_remain, &secs_remain); | |
364 | |
365 mexPrintf("omp: signal %d / %d, estimated remaining time: %02d:%02d:%05.2f\n", | |
366 signum+1, L, hrs_remain, mins_remain, secs_remain); | |
367 mexEvalString("drawnow;"); | |
368 } | |
369 | |
370 } | |
371 | |
372 /* end omp */ | |
373 | |
374 | |
375 | |
376 /*** print final messages ***/ | |
377 | |
378 if (msg_delta>0) { | |
379 mexPrintf("omp: signal %d / %d\n", signum, L); | |
380 } | |
381 | |
382 if (profile) { | |
383 printprofinfo(&pd, erroromp, batchomp, L); | |
384 } | |
385 | |
386 | |
387 | |
388 /* free memory */ | |
389 | |
390 if (!DtX_specified) { | |
391 mxFree(DtX); | |
392 } | |
393 if (standardomp) { | |
394 mxFree(r); | |
395 mxFree(Dsub); | |
396 } | |
397 else { | |
398 mxFree(Gsub); | |
399 } | |
400 mxFree(tempvec2); | |
401 mxFree(tempvec1); | |
402 mxFree(Lchol); | |
403 mxFree(c); | |
404 mxFree(selected_atoms); | |
405 mxFree(ind); | |
406 mxFree(alpha); | |
407 | |
408 return Gamma; | |
409 } |