annotate util/ksvd utils/ompbox utils/ompcoreGabor.c @ 137:9207d56c5547 ivand_dev

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