/* qsmodel.c headerfile for quasistatic probability model (c) Michael Schindler 1997, 1998 http://www.compressconsult.com/ or http://eiunix.tuwien.ac.at/~michael michael@compressconsult.com michael@eiunix.tuwien.ac.at This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. It may be that this program violates local patents in your country, however it is belived (NO WARRANTY!) to be patent-free here in Austria. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Qsmodel is a quasistatic probability model that periodically (at chooseable intervals) updates probabilities of symbols; it also allows to initialize probabilities. Updating is done more frequent in the beginning, so it adapts very fast even without initialisation. it provides function for creation, deletion, query for probabilities and symbols and model updating. for usage see example.c */ #include "qsmodel.h" #include #include /* default tablesize 1<nextleft) /* we have some more before actual rescaling */ { m->incr++; m->left = m->nextleft; m->nextleft = 0; return; } if (m->rescale < m->targetrescale) /* double rescale interval if needed */ { m->rescale <<= 1; if (m->rescale > m->targetrescale) m->rescale = m->targetrescale; } cf = missing = m->cf[m->n]; /* do actual rescaling */ for(i=m->n-1; i; i--) { int tmp = m->newf[i]; cf -= tmp; m->cf[i] = cf; tmp = tmp>>1 | 1; missing -= tmp; m->newf[i] = tmp; } if (cf!=m->newf[0]) { fprintf(stderr,"BUG: rescaling left %d total frequency\n",cf); deleteqsmodel(m); exit(1); } m->newf[0] = m->newf[0]>>1 | 1; missing -= m->newf[0]; m->incr = missing / m->rescale; m->nextleft = missing % m->rescale; m->left = m->rescale - m->nextleft; if (m->search != NULL) { i=m->n; while (i) { int start, end; end = (m->cf[i]-1) >> m->searchshift; i--; start = m->cf[i] >> m->searchshift; while (start<=end) { m->search[start] = i; start++; } } } } /* initialisation of qsmodel */ /* m qsmodel to be initialized */ /* n number of symbols in that model */ /* lg_totf base2 log of total frequency count */ /* rescale desired rescaling interval, should be < 1<<(lg_totf+1) */ /* init array of int's to be used for initialisation (NULL ok) */ /* compress set to 1 on compression, 0 on decompression */ void initqsmodel( qsmodel *m, int n, int lg_totf, int rescale, int *init, int compress ) { m->n = n; m->targetrescale = rescale; m->searchshift = lg_totf - TBLSHIFT; if (m->searchshift < 0) m->searchshift = 0; m->cf = (uint2*) malloc((n+1)*sizeof(uint2)); m->newf = (uint2*) malloc((n+1)*sizeof(uint2)); m->cf[n] = 1<cf[0] = 0; if (compress) m->search = NULL; else { m->search = (uint2*) malloc(((1<search[1<rescale = m->n>>4 | 2; m->nextleft = 0; if (init == NULL) { initval = m->cf[m->n] / m->n; end = m->cf[m->n] % m->n; for (i=0; inewf[i] = initval+1; for (; in; i++) m->newf[i] = initval; } else for(i=0; in; i++) m->newf[i] = init[i]; dorescale(m); } /* deletion of qsmodel m */ void deleteqsmodel( qsmodel *m ) { free(m->cf); free(m->newf); if (m->search != NULL) free(m->search); } /* retrieval of estimated frequencies for a symbol */ /* m qsmodel to be questioned */ /* sym symbol for which data is desired; must be cf[sym+1] - (*lt_f = m->cf[sym]); } /* find out symbol for a given cumulative frequency */ /* m qsmodel to be questioned */ /* lt_f cumulative frequency */ int qsgetsym( qsmodel *m, int lt_f ) { int lo, hi; uint2 *tmp; tmp = m->search+(lt_f>>m->searchshift); lo = *tmp; hi = *(tmp+1) + 1; while (lo+1 < hi ) { int mid = (lo+hi)>>1; if (lt_f < m->cf[mid]) hi = mid; else lo = mid; } return lo; } /* update model */ /* m qsmodel to be updated */ /* sym symbol that occurred (must be left <= 0) dorescale(m); m->left--; m->newf[sym] += m->incr; }