src/quantizer.c

Go to the documentation of this file.
00001 /*
00002    libit - Library for basic source and channel coding functions
00003    Copyright (C) 2005-2005 Vivien Chappelier, Herve Jegou
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /*
00021   Quantizers
00022   Copyright (C) 2005 Vivien Chappelier
00023 */
00024 
00025 #include <stdarg.h>
00026 #include <it/types.h>
00027 #include <it/vec.h>
00028 #include <it/math.h>
00029 #include <it/quantizer.h>
00030 #include <it/io.h>
00031 
00032 /* function prototypes */
00033 static void scalar_quantizer_destructor (it_object_t * it_this);
00034 static vec scalar_quantizer_get_codebook_range (it_scalar_quantizer_t * q,
00035             int start, int end);
00036 static void scalar_quantizer_get_index_range (it_scalar_quantizer_t * q,
00037                 int *_imin, int *_imax);
00038 static void scalar_quantizer_set_index_range (it_scalar_quantizer_t * q,
00039                 int _imin, int _imax);
00040 static int scalar_quantizer_scalar_quantize (it_scalar_quantizer_t * q,
00041                double v);
00042 static double scalar_quantizer_scalar_dequantize (it_scalar_quantizer_t *
00043               it_this, int q);
00044 static void scalar_quantizer_set_codebook (it_scalar_quantizer_t * it_this,
00045              vec codebook, int first);
00046 static ivec scalar_quantizer_quantize (it_quantizer_t * it_this, vec v);
00047 static vec scalar_quantizer_dequantize (it_quantizer_t * it_this, ivec q);
00048 static unsigned int scalar_quantizer_get_cardinal (it_quantizer_t * it_this);
00049 
00050 static int uniform_quantizer_scalar_quantize (it_scalar_quantizer_t *
00051                 it_this, double v);
00052 static double uniform_quantizer_scalar_dequantize (it_scalar_quantizer_t *
00053                it_this, int q);
00054 static vec uniform_quantizer_get_codebook_range (it_scalar_quantizer_t *
00055              it_this, int s, int e);
00056 static void uniform_quantizer_set_index_range (it_scalar_quantizer_t * q,
00057                  int _imin, int _imax);
00058 static void uniform_quantizer_set_codebook (it_scalar_quantizer_t * it_this,
00059               vec codebook, int first);
00060 
00061 static void trellis_coded_quantizer_destructor (it_object_t * it_this);
00062 static ivec trellis_coded_quantizer_quantize (it_quantizer_t * it_this,
00063                 vec v);
00064 static vec trellis_coded_quantizer_dequantize (it_quantizer_t * it_this,
00065                  ivec q);
00066 static unsigned int trellis_coded_quantizer_get_cardinal (it_quantizer_t *
00067                 it_this);
00068 
00069 
00070 /* instanciation of a scalar quantizer */
00071 it_instanciate (it_scalar_quantizer_t)
00072 {
00073   vec  codebook;
00074 
00075   /* start variable argument list */
00076   it_new_args_start ();
00077 
00078   /* call the parent constructor */
00079   it_construct (it_quantizer_t);
00080 
00081   /* set the appropriate magic */
00082   it_set_magic (it_this, it_scalar_quantizer_t);
00083 
00084   /* overload the virtual destructor */
00085   it_overload (it_this, it_object_t, destructor, scalar_quantizer_destructor);
00086 
00087   /* assign methods */
00088   IT_QUANTIZER (it_this)->quantize = scalar_quantizer_quantize;
00089   IT_QUANTIZER (it_this)->dequantize = scalar_quantizer_dequantize;
00090   IT_QUANTIZER (it_this)->get_cardinal = scalar_quantizer_get_cardinal;
00091   it_this->set_codebook = scalar_quantizer_set_codebook;
00092   it_this->get_codebook_range = scalar_quantizer_get_codebook_range;
00093   it_this->get_index_range = scalar_quantizer_get_index_range;
00094   it_this->set_index_range = scalar_quantizer_set_index_range;
00095   it_this->scalar_quantize = scalar_quantizer_scalar_quantize;
00096   it_this->scalar_dequantize = scalar_quantizer_scalar_dequantize;
00097 
00098   /* construction */
00099   codebook = it_new_args_next (vec);
00100   it_this->first = it_new_args_next (int);
00101 
00102   if (codebook)
00103     scalar_quantizer_set_codebook (it_this, codebook, it_this->first);
00104   else {
00105     it_this->codebook = NULL;
00106     it_scalar_quantizer_set_index_range (it_this, 0, -1);
00107   }
00108 
00109   it_new_args_stop ();
00110   return (it_this);
00111 }
00112 
00113 static void scalar_quantizer_destructor (it_object_t * it_this)
00114 {
00115   it_scalar_quantizer_t *scalar_quantizer = IT_SCALAR_QUANTIZER (it_this);
00116 
00117   if (scalar_quantizer->codebook)
00118     vec_delete (scalar_quantizer->codebook);
00119 
00120   /* call the parent destructor */
00121   scalar_quantizer->it_overloaded (destructor) (it_this);
00122 }
00123 
00124 static vec scalar_quantizer_get_codebook_range (it_scalar_quantizer_t * q,
00125             int start, int end)
00126 {
00127   if (start < q->imin)
00128     start = q->imin;
00129   if (end > q->imax)
00130     end = q->imax;
00131   return (vec_get_subvector (q->codebook, start, end));
00132 }
00133 
00134 static void scalar_quantizer_get_index_range (it_scalar_quantizer_t * q,
00135                 int *_imin, int *_imax)
00136 {
00137   *_imax = q->imax;
00138   *_imin = q->imin;
00139 }
00140 
00141 static void scalar_quantizer_set_index_range (it_scalar_quantizer_t * q,
00142                 int _imin, int _imax)
00143 {
00144   if (_imin < _imax) {
00145     q->imax = _imax;
00146     q->imin = _imin;
00147   }
00148   else {
00149     q->imax = _imin;
00150     q->imin = _imax;
00151   }
00152 
00153   if (q->imin < q->first)
00154     q->imin = q->first;
00155   if (q->codebook) {
00156     if (q->imax > q->first + (int) vec_length (q->codebook) - 1)
00157       q->imax = q->first + (int) vec_length (q->codebook) - 1;
00158   }
00159   else {
00160     q->imax = q->imin;
00161   }
00162 }
00163 
00164 /* scalar quantization */
00165 static int scalar_quantizer_scalar_quantize (it_scalar_quantizer_t * q,
00166                double v)
00167 {
00168   int  s, e, h;
00169   double c;
00170   int  first = q->first;
00171   vec  codebook = q->codebook;
00172 
00173   /* logarithmic search for the index of the closest vector */
00174   s = q->imin - first;
00175   e = q->imax - first;
00176 
00177   while (e > s + 1) {
00178     /* compare with the median of the range */
00179     h = (s + e) / 2;
00180     c = codebook[h];
00181 
00182     /* narrow down the range */
00183     if (v < c)
00184       e = h;
00185     else
00186       s = h;
00187   }
00188 
00189   /* find the closest vector */
00190   if (v - codebook[s] < codebook[e] - v)
00191     return (s + first);
00192   else
00193     return (e + first);
00194 }
00195 
00196 /* scalar dequantization */
00197 static double scalar_quantizer_scalar_dequantize (it_scalar_quantizer_t *
00198               it_this, int q)
00199 {
00200   int  first = it_this->first;
00201   return (it_this->codebook[q - first]);
00202 }
00203 
00204 /* change the codebook */
00205 static void scalar_quantizer_set_codebook (it_scalar_quantizer_t * it_this,
00206              vec codebook, int first)
00207 {
00208   if (!codebook) {
00209     fprintf (stderr,
00210        "scalar_quantizer_set_codebook called with a NULL codebook\n");
00211     abort ();
00212   }
00213 
00214   it_this->codebook = vec_clone (codebook);
00215   it_this->first = first;
00216   it_scalar_quantizer_set_index_range (it_this, first,
00217                first + vec_length (codebook) - 1);
00218   /* sort the codebook in increasing order */
00219   vec_sort (it_this->codebook);
00220 }
00221 
00222 /* quantize the vector v */
00223 static ivec scalar_quantizer_quantize (it_quantizer_t * it_this, vec v)
00224 {
00225   it_scalar_quantizer_t *scalar_quantizer = IT_SCALAR_QUANTIZER (it_this);
00226   int  i;
00227   int  l = vec_length (v);
00228   ivec ret = ivec_new (l);
00229 
00230   for (i = 0; i < l; i++)
00231     ret[i] = it_scalar_quantizer_scalar_quantize (scalar_quantizer, v[i]);
00232 
00233   return (ret);
00234 }
00235 
00236 /* dequantize the indices vector q */
00237 static vec scalar_quantizer_dequantize (it_quantizer_t * it_this, ivec q)
00238 {
00239   it_scalar_quantizer_t *scalar_quantizer = IT_SCALAR_QUANTIZER (it_this);
00240   int  i;
00241   int  l = ivec_length (q);
00242   vec  ret = vec_new (l);
00243 
00244   for (i = 0; i < l; i++)
00245     ret[i] = it_scalar_quantizer_scalar_dequantize (scalar_quantizer, q[i]);
00246 
00247   return (ret);
00248 }
00249 
00250 /* get the number of codewords for the uniform scalar quantizer */
00251 static unsigned int scalar_quantizer_get_cardinal (it_quantizer_t * it_this)
00252 {
00253   int  imin = IT_SCALAR_QUANTIZER (it_this)->imin;
00254   int  imax = IT_SCALAR_QUANTIZER (it_this)->imax;
00255 
00256   return (imax - imin + 1); /* may overflow, that's ok, 0 means 'infinite' */
00257 }
00258 
00259 /*---------------------- Uniform Quantizer -----------------------------*/
00260 
00261 it_instanciate (it_uniform_quantizer_t)
00262 {
00263   it_new_args_start ();
00264 
00265   /* construct a scalar quantizer with empty codebook */
00266   it_construct_va (it_scalar_quantizer_t) (it_va, NULL, 0);
00267   it_set_magic (it_this, it_uniform_quantizer_t);
00268 
00269   /* assign/overload methods */
00270   IT_SCALAR_QUANTIZER (it_this)->scalar_quantize =
00271     uniform_quantizer_scalar_quantize;
00272   IT_SCALAR_QUANTIZER (it_this)->scalar_dequantize =
00273     uniform_quantizer_scalar_dequantize;
00274   IT_SCALAR_QUANTIZER (it_this)->get_codebook_range =
00275     uniform_quantizer_get_codebook_range;
00276   IT_SCALAR_QUANTIZER (it_this)->set_index_range =
00277     uniform_quantizer_set_index_range;
00278   IT_SCALAR_QUANTIZER (it_this)->set_codebook =
00279     uniform_quantizer_set_codebook;
00280 
00281   /* construction */
00282   it_this->center = it_new_args_next (double);
00283   it_this->step = it_new_args_next (double);
00284   it_this->factor = it_new_args_next (double);
00285   it_this->deadzone = it_this->step * it_this->factor;
00286   it_scalar_quantizer_clear_index_range (it_this);
00287 
00288   it_new_args_stop ();
00289   return (it_this);
00290 }
00291 
00292 static int uniform_quantizer_scalar_quantize (it_scalar_quantizer_t *
00293                 it_this, double v)
00294 {
00295   int  imin = it_this->imin;
00296   int  imax = it_this->imax;
00297   double min = IT_UNIFORM_QUANTIZER (it_this)->min;
00298   double max = IT_UNIFORM_QUANTIZER (it_this)->max;
00299   double center = it_quantizer_get_center (it_this);
00300   double step = it_quantizer_get_step (it_this);
00301   double dead_step = it_quantizer_get_deadzone_step (it_this);
00302 
00303   if (v <= min)
00304     return (imin);
00305   if (v >= max)
00306     return (imax);
00307 
00308   v -= center;      /* center the value */
00309 
00310   if (v > 0)      /* divide and round */
00311     return ((int) ((v + step - dead_step / 2) / step));
00312   else
00313     return ((int) ((v - step + dead_step / 2) / step));
00314 }
00315 
00316 /* uniform scalar dequantization */
00317 static double uniform_quantizer_scalar_dequantize (it_scalar_quantizer_t *
00318                it_this, int q)
00319 {
00320   double center = it_quantizer_get_center (it_this);
00321   double step = it_quantizer_get_step (it_this);
00322   double dead_step = it_quantizer_get_deadzone_step (it_this);
00323 
00324   if (q == 0)
00325     return (center);
00326 
00327   if (q > 0)
00328     return (center + q * step + (dead_step - step) / 2);
00329   else
00330     return (center + q * step - (dead_step - step) / 2);
00331 }
00332 
00333 /* dynamically generate the codebook... use with caution */
00334 static vec uniform_quantizer_get_codebook_range (it_scalar_quantizer_t *
00335              it_this, int s, int e)
00336 {
00337   int  imin = it_this->imin;
00338   int  imax = it_this->imax;
00339   vec  book;
00340   int  i;
00341 
00342   if (it_this->codebook)
00343     return (it_scalar_quantizer_get_codebook_range (it_this, s, e));
00344 
00345   if (s < imin)
00346     s = imin;
00347   if (e > imax)
00348     e = imax;
00349   book = vec_new (e - s + 1);
00350 
00351   for (i = s; i <= e; i++)
00352     book[i - s] = it_scalar_quantizer_scalar_dequantize (it_this, i);
00353 
00354   return (book);
00355 }
00356 
00357 static void uniform_quantizer_set_index_range (it_scalar_quantizer_t *
00358                  it_this, int _imin, int _imax)
00359 {
00360   if (_imin < _imax) {
00361     it_this->imax = _imax;
00362     it_this->imin = _imin;
00363   }
00364   else {
00365     it_this->imax = _imin;
00366     it_this->imin = _imax;
00367   }
00368 
00369   IT_UNIFORM_QUANTIZER (it_this)->min = it_dequantize (it_this, _imin);
00370   IT_UNIFORM_QUANTIZER (it_this)->max = it_dequantize (it_this, _imax);
00371 }
00372 
00373 /* change the codebook */
00374 static void uniform_quantizer_set_codebook (it_scalar_quantizer_t * it_this,
00375               vec codebook, int first)
00376 {
00377   fprintf (stderr, "cannot change the codebook of a uniform quantizer\n");
00378   abort ();
00379 }
00380 
00381 /*----------------- Trellis Coded Quantizer ----------------------------*/
00382 
00383 /* gray code to binary code */
00384 #define gray_to_bin(x) ((x) ^ (x >> 1))
00385 
00386 it_instanciate (it_trellis_coded_quantizer_t)
00387 {
00388   int  i, j, k;
00389   int  n, r, m;
00390 
00391   vec  codebook;
00392   vec  subcodebook;
00393   it_convolutional_code_t *code;
00394   it_scalar_quantizer_t *quantizer;
00395   it_scalar_quantizer_t **coset_quantizers;
00396 
00397   it_new_args_start ();
00398 
00399   it_construct (it_quantizer_t);
00400   it_set_magic (it_this, it_trellis_coded_quantizer_t);
00401 
00402   /* assign/overload methods */
00403   it_overload (it_this, it_object_t, destructor,
00404          trellis_coded_quantizer_destructor);
00405   IT_QUANTIZER (it_this)->quantize = trellis_coded_quantizer_quantize;
00406   IT_QUANTIZER (it_this)->dequantize = trellis_coded_quantizer_dequantize;
00407   IT_QUANTIZER (it_this)->get_cardinal = trellis_coded_quantizer_get_cardinal;
00408 
00409   /* construction */
00410   code = it_new_args_next (it_convolutional_code_t *);
00411   quantizer = it_new_args_next (it_scalar_quantizer_t *);
00412   it_this->code = code;   /* TODO: deep copy? */
00413 
00414   /* retrieve the codebook */
00415   codebook = it_quantizer_get_codebook (quantizer);
00416   n = vec_length (codebook);
00417   r = code->n;
00418   m = (1 << r);
00419 
00420   /* set partitioning of the codebook */
00421   it_this->coset_quantizers = coset_quantizers =
00422     (it_scalar_quantizer_t **) malloc (m * sizeof (it_scalar_quantizer_t *));
00423 
00424   for (j = 0; j < m; j++) {
00425     subcodebook = vec_new ((n + m - j - 1) / m);
00426 
00427     for (i = j, k = 0; i < n; i += m, k++)
00428       subcodebook[k] = codebook[i];
00429 
00430     coset_quantizers[gray_to_bin (j)] = it_scalar_quantizer_new (subcodebook);
00431     vec_delete (subcodebook);
00432   }
00433 
00434   it_new_args_stop ();
00435   return (it_this);
00436 }
00437 
00438 /* TCQ destructor */
00439 static void trellis_coded_quantizer_destructor (it_object_t * it_this)
00440 {
00441   it_trellis_coded_quantizer_t *tcq = IT_TRELLIS_CODED_QUANTIZER (it_this);
00442   it_scalar_quantizer_t **coset_quantizers = tcq->coset_quantizers;
00443   int  m = 1 << tcq->code->n; /* number of cosets */
00444   int  i;
00445 
00446   for (i = 0; i < m; i++)
00447     it_delete (coset_quantizers[i]);
00448 
00449   /* TODO: destruct the code? (if deep copy) */
00450 
00451   /* call the parent destructor */
00452   tcq->it_overloaded (destructor) (it_this);
00453 }
00454 
00455 /* quantize the vector v */
00456 static ivec trellis_coded_quantizer_quantize (it_quantizer_t * it_this, vec v)
00457 {
00458   it_trellis_coded_quantizer_t *tcq = IT_TRELLIS_CODED_QUANTIZER (it_this);
00459   it_scalar_quantizer_t **coset_quantizers = tcq->coset_quantizers;
00460   it_convolutional_code_t *cc = tcq->code;
00461   mat  metrics;
00462   imat bestword;
00463   int  i, j, q;
00464   double r;
00465   int  l = vec_length (v);
00466   int  n_labels = cc->n_labels;
00467   ivec ret = ivec_new (l);
00468   ivec path;
00469   ivec books;
00470 
00471   /* fill the metrics and best words */
00472   metrics = mat_new (n_labels, l);
00473   bestword = imat_new (n_labels, l);
00474 
00475   for (i = 0; i < l; i++)
00476     for (j = 0; j < n_labels; j++) {
00477       /* quantize in the coset associated with the branch label */
00478       q = it_quantize (coset_quantizers[j], v[i]);
00479       r = it_dequantize (coset_quantizers[j], q);
00480       /* compute the distortion associated to that label */
00481       metrics[j][i] = -(r - v[i]) * (r - v[i]);
00482       bestword[j][i] = q;
00483     }
00484 
00485   /* search for the sequence of minimal distortion */
00486   path = it_viterbi_decode_symbolic (cc, metrics);
00487 
00488   /* get the sequence of codebooks */
00489   books = it_cc_encode_symbolic (cc, path);
00490 
00491   /* merge the index and path bits to codeword bits */
00492   for (i = 0; i < l; i++)
00493     ret[i] = (bestword[books[i]][i] << 1) | path[i];
00494 
00495   mat_delete (metrics);
00496   imat_delete (bestword);
00497 
00498   ivec_delete (path);
00499   ivec_delete (books);
00500 
00501   return (ret);
00502 }
00503 
00504 /* dequantize the indices vector q */
00505 static vec trellis_coded_quantizer_dequantize (it_quantizer_t * it_this,
00506                  ivec q)
00507 {
00508   it_trellis_coded_quantizer_t *tcq = IT_TRELLIS_CODED_QUANTIZER (it_this);
00509   it_scalar_quantizer_t **coset_quantizers = tcq->coset_quantizers;
00510   it_convolutional_code_t *cc = tcq->code;
00511   int  i;
00512   int  l = ivec_length (q);
00513   vec  ret = vec_new (l);
00514   ivec path;      /* path bits */
00515   ivec books;     /* sequence of codebooks */
00516   int  word;
00517 
00518   /* split the index into path bits and codeword bits */
00519   path = ivec_new (l);
00520   for (i = 0; i < l; i++)
00521     path[i] = q[i] & 1;
00522 
00523   /* get the sequence of codebooks */
00524   books = it_cc_encode_symbolic (cc, path);
00525 
00526   /* dequantize using the appropriate codebook */
00527   for (i = 0; i < l; i++) {
00528     word = q[i] >> 1;
00529     ret[i] = it_dequantize (coset_quantizers[books[i]], word);
00530   }
00531 
00532   ivec_delete (path);
00533   ivec_delete (books);
00534   return (ret);
00535 }
00536 
00537 
00538 /* get the number of codewords for the TCQ quantizer */
00539 static unsigned int trellis_coded_quantizer_get_cardinal (it_quantizer_t *
00540                 it_this)
00541 {
00542   it_trellis_coded_quantizer_t *tcq = IT_TRELLIS_CODED_QUANTIZER (it_this);
00543   it_convolutional_code_t *cc = tcq->code;
00544   int  k = cc->k;   /* number of path bits */
00545   int  c = it_quantizer_get_cardinal (tcq->coset_quantizers[0]);  /* number of codewords */
00546 
00547   return ((1 << k) * c);
00548 }
00549 
00550 
00551 /*----------------- Helper functions ----------------------------*/
00552 
00553 /* used to compute the distortion in Lloyd-Max */
00554 it_function_args (lloyd_max_distortion)
00555 {
00556   double expectation;   /* reconstruction value */
00557   it_function_t function; /* function to integrate */
00558   it_args_t args;   /* and its arguments */
00559 };
00560 
00561 it_function (lloyd_max_distortion)
00562 {
00563   double E = it_this->expectation;
00564   it_function_t f = it_this->function;
00565   it_args_t args = it_this->args;
00566   double d;
00567 
00568   d = x - E;
00569 
00570   return (d * d * f (x, args));
00571 }
00572 
00573 
00574 /* find the optimal codebook for a stationnary i.i.d. source */
00575 /* the algorithm stops when the relative difference in distortion */
00576 /* is smaller than IT_EPSILON. */
00577 vec lloyd_max (it_function_t function, it_args_t args,
00578          double a, double b, int N)
00579 {
00580   /* for the initial guess, use a scalar quantizer of step (b-a)/N */
00581   double step = (b - a) / N;
00582   vec  threshold = vec_new_arithm (a, step, N + 1);
00583   vec  codebook = vec_new_arithm (a, step, N);
00584   int  i;
00585   double density;
00586   double expectation;
00587   double distortion, old_distortion;
00588   it_function_args (itf_integrate) density_args;
00589   it_function_args (itf_expectation) expectation_args;
00590   it_function_args (lloyd_max_distortion) distortion_args;
00591   it_function_args (itf_integrate) integrate_args;
00592 
00593   /* for integrating f(x) */
00594   density_args.function = function;
00595   density_args.args = args;
00596   /* for integrating x * f(x) */
00597   expectation_args.function = function;
00598   expectation_args.args = args;
00599   /* for integrating (x - E[X])^2 * f(x) */
00600   distortion_args.function = function;
00601   distortion_args.args = args;
00602   integrate_args.function = lloyd_max_distortion;
00603   integrate_args.args = &distortion_args;
00604 
00605   distortion = HUGE_VAL;
00606 
00607   do {
00608 
00609     old_distortion = distortion;
00610     distortion = 0;
00611 
00612     /* compute centroids */
00613     for (i = 0; i < N; i++) {
00614       /* integrate f(x) between threshold[i] and threshold[i+1] */
00615       density_args.a = threshold[i];
00616       density = itf_integrate (threshold[i + 1], &density_args);
00617 
00618       /* integrate xf(x) between threshold[i] and threshold[i+1] */
00619       expectation_args.a = threshold[i];
00620       expectation = itf_expectation (threshold[i + 1], &expectation_args);
00621 
00622       codebook[i] = expectation / density;
00623 
00624       /* integrate (x - E)^2 f(x) */
00625       integrate_args.a = threshold[i];
00626       distortion_args.expectation = codebook[i];
00627       distortion += itf_integrate (threshold[i + 1], &integrate_args);
00628     }
00629 
00630     /* compute thresholds */
00631     for (i = 0; i < N - 1; i++)
00632       threshold[i + 1] = (codebook[i] + codebook[i + 1]) / 2.0;
00633 
00634   }
00635   while ((old_distortion - distortion) / distortion > IT_EPSILON);
00636 
00637   return (codebook);
00638 }
00639 
00640 /* Matrix quantization: each line is quantized independently */
00641 imat __it_quantize_mat (it_quantizer_t * q, mat m)
00642 {
00643   idx_t i, h;
00644   imat r;
00645   h = mat_height (m);
00646   r = (ivec *) Vec_new (ivec, h);
00647   for (i = 0; i < h; i++)
00648     r[i] = it_quantize_vec (q, m[i]);
00649   return (r);
00650 }
00651 
00652 /* Matrix dequantization: each line is dequantized independently */
00653 mat __it_dequantize_mat (it_quantizer_t * q, imat m)
00654 {
00655   idx_t i, h;
00656   mat  r;
00657   h = imat_height (m);
00658   r = (vec *) Vec_new (vec, h);
00659   for (i = 0; i < h; i++)
00660     r[i] = it_dequantize_vec (q, m[i]);
00661   return (r);
00662 }

Hosted by
Copyright (C) 2005-2006 Hervé Jégou
Vivien Chappelier
Francois Cayre
libit logo courtesy of Jonathan Delhumeau