-/*
- Copyright (C) Arturo San Emeterio Campos 1999. All rights reserved.
- Permission is granted to make verbatim copies of this file for private
- use only. There is ABSOLUTELY NO WARRANTY. Use it at your OWN RISK.
-
- This file is: "ppmc.c"
- Email: arturo@arturocampos.com
- Web: http://www.arturocampos.com
-
- Part of the ppmc encoder and decoder.
-
- This module contains the whole ppmc encoder. It uses hash tables for
- managing most of the orders. And a maximum order of 4. It codes bytes.
- Order-1-0-(-1) are all handled in tables. Order-2 has a table with
- direct hashing with pointers to the linked lists. Order-4 and order-3
- both have hash tables with pointers to contexts in a linked lists which
- finally have a pointer to the start of the linked list with the
- probability distribution. Update exclusion is used, but exclusion is not.
-
- Please, note that if the machine where the decoder is run doesn't has as
- much memory as the computer where the encoder was ran, the decoder will
- not be able to properly decode the file, because it will not be able to
- keep track of new statistics, in this case it will just exit.
-
- For applications where the loss of data is not admisible, I suggest you to
- limit both encoder and decoder's memory requeriments to a given minimum
- which both machines have.
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "range.h"
-#include "ppmcdata.h"
-
-static unsigned ordern1_table[] = {
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 4303574, 88451153, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 143318, 9172380, 1146547, 100, 143318, 573273, 859910, 10318928,
- 10318928, 6019374, 573273, 26657231, 1576502, 43138853, 10462246, 3439642,
- 6162693, 6162693, 6162693, 6162693, 6162693, 6162693, 6162693, 6162693,
- 6162693, 6162693, 8742425, 4299553, 14188526, 3439642, 9888973, 429955,
- 143318, 27230505, 2436413, 22357678, 10892202, 40989076, 1576502, 1433184,
- 286636, 37406115, 573273, 286636, 19204672, 13901889, 19491309, 10462246,
- 16481621, 1003229, 21211130, 13615252, 17914806, 2866368, 4012916, 429955,
- 1719821, 1146547, 143318, 286636, 143318, 286636, 143318, 1576502,
- 143318, 315013952, 32246651, 165962764, 171122228, 418203235, 23790862, 26800550,
- 17054895, 230742703, 7452559, 1003229, 163669669, 75385504, 225153284, 261412851,
- 88140846, 24794091, 215837585, 223003507, 162523121, 110355206, 38122707, 5302782,
- 7595877, 18918035, 8885743, 859910, 100, 859910, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 100, 100, 100, 100,
-};
-#define ordern1_total_cump 3651941255u
-
-// Ruotines used by ppmc. Not including the range coder.
-//
-// They are for initializing of both encoder and decoder, and unless there
-// are two version, both encoder and decoder use the same routines. Like
-// "ppmc_initialize_contexts".
-
-
-// This one allocs the memory needed by ppmc, and adjust some pointers used
-// for allocating elements in the linked lists. The mempool arrays must be
-// initialized now.
-void ppmc_alloc_memory(void)
-{
- unsigned long counter;
-
-
- // Init mempool buffers
-
- for(counter=0;counter!=_mempool_max_index;++counter)
- {
- _bytes_pool_array[counter]=0;
- _context_pool_array[counter]=0;
- }
-
- _bytes_pool_index=1; //first entry will be used now
- _context_pool_index=1;
-
-
- // Allocate memory for ppmc structures and adjust some variables
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
-
- //save pointers in the array for freeing
- _bytes_pool_array[0]=_bytes_pool;
- _context_pool_array[0]=_context_pool;
-
-
- //adjust variables
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements;
- _context_pool_max=_context_pool+_context_pool_elements;
-
- ppmc_out_of_memory=0; //we still have memory
-}
-
-
-// This routine initializes all the contexts, and all the tables including
-// those who care about the number of bytes defined in a context.
-void ppmc_initialize_contexts(void)
-{
- unsigned long counter, counter2;
-
-
- // Order-0
- for(counter=0;counter!=256;++counter) //clear table
- order0_array[counter]=0;
-
- order0_defined_bytes=0; //adjust variables
- order0_max_cump=0;
-
-
- // Order-1
- for(counter=0;counter!=256;++counter) //erase every table of every context
- for(counter2=0;counter2!=256;++counter2)
- order1_array[counter][counter2]=0;
-
- for(counter=0;counter!=256;++counter) //adjust variables
- {
- order1_defined_bytes_array[counter]=0;
- order1_max_cump_array[counter]=0;
- }
-
-
- // Order-2
- for(counter=0;counter!=65536;++counter)
- {
- //order2_array[counter].prob=0; //clear pointer to bytes and frequencies
- //order2_array[counter].max_cump=0;
- order2_array[counter].defined_bytes=0;
- }
-
-
- // Order-4-3
- for(counter=0;counter!=65536;++counter) //order-4-3
- {
- order4_hasht[counter]=0;
- order3_hasht[counter]=0;
- }
-}
-
-
-// This routine initializes the encode model by outputting as many bytes as
-// needed to prepare the models. This should be called before the main loop
-// and after the memory has been allocated and tables initialized.
-//
-// It does not need uses the range coder. It output the first 1 bytes.
-void ppmc_encoder_initialize(void)
-{
-
- // Initialize order-0 and prepare different bytes for orders
- fputc((byte=fgetc(file_input)),file_output);
- o4_byte=byte; //order-4
-
- fputc((byte=fgetc(file_input)),file_output);
- o3_byte=byte; //order-3
-
- fputc((byte=fgetc(file_input)),file_output);
- o2_byte=byte; //order-2
- ppmc_update_order0();
-
- fputc((byte=fgetc(file_input)),file_output);
- o1_byte=byte;
-
-}
-
-
-// This routine initializes the decoder model, should be called to do the same
-// changes as "ppmc_encoder_initialize()" did.
-void ppmc_decoder_initialize(void)
-{
-
- // Initialize order-0 and context bytes
- byte=fgetc(file_input);
- o4_byte=byte; //order-4
- fputc(byte,file_output);
-
- byte=fgetc(file_input);
- o3_byte=byte; //order-3
- fputc(byte,file_output);
-
- byte=fgetc(file_input);
- o2_byte=byte; //order-2
-
- fputc(byte,file_output); //output first byte
- ppmc_update_order0();
-
- byte=fgetc(file_input);
- o1_byte=byte; //order-1
- fputc(byte,file_output);
-}
-
-
-// Once coding or decoding is finished you have to call this routine.
-// It must be called when done.
-void ppmc_free_memory(void)
-{
- unsigned long counter;
-
- // Free the memory buffers
-
- for(counter=0;counter!=_mempool_max_index;++counter)
- {
- if(_bytes_pool_array[counter]!=0)
- free(_bytes_pool_array[counter]);
-
- if(_context_pool_array[counter]!=0)
- free(_context_pool_array[counter]);
- }
-
-}
-
-
-// This routine flushes the memory and restarts all the tables of
-// probabilities, current order bytes are not modified, this function
-// is called when we ran out of memory. We have to output the code
-// number 256 which means memory flushing, for doing this we have to go
-// to order-(-1) so we have to output an escape code in all the orders
-// till we reach order-(-1) where we can code it. Then we free all the
-// memory, alloc it again, and reinitialize all the orders.
-//
-// However we may find the case when the current order is not initialized,
-// in this case we don't need to output an escape code.
-void ppmc_flush_mem_enc(void)
-{
-
- // Code an escape code in order-4
- if(ppmc_get_totf_order4()!=0) //if 0 no need of escape code
- {
-
- ppmc_get_escape_prob_order4(); //get prob and cump
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- }
-
-
- // Code an escape code in order-3
- if(ppmc_get_totf_order3()!=0) //if 0 no need of escape code
- {
-
- ppmc_get_escape_prob_order3(); //get prob and cump
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- }
-
-
- // Code an escape code in order-2
-
- o2_cntxt=ppmc_order2_hash_key(o1_byte,o2_byte);
-
- // First check if current order-2 context is empty
- if(order2_array[o2_cntxt].defined_bytes!=0) //it's not empty
- {
- ppmc_get_totf_order2();
- ppmc_get_escape_prob_order2();
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
- }
-
-
- // Code an escape code in order-1
-
- // First check if current order-1 table is empty
- if(order1_defined_bytes_array[o1_byte]!=0) //it's not empty
- {
- ppmc_get_totf_order1();
- ppmc_get_escape_prob_order1();
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
- }
-
-
- // Code an escape code in order-0. Order-0 always has at least one symbol
-
- ppmc_get_totf_order0();
- ppmc_get_escape_prob_order0();
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
-
-
- // Now we can code the code 256
-
- symb_prob=1;
- symb_cump=256;
- total_cump=257;
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
-
- // Now that decoder knows the flushing, free memory and reinit
-
- ppmc_free_memory();
- ppmc_alloc_memory();
- ppmc_initialize_contexts();
-
-
- // Be sure that order-0 has at least one probability
-
- order0_array[o1_byte]++;
- order0_max_cump++;
- order0_defined_bytes++;
-
-}
-
-
-// When the decoder gets the symbol of flushing, most of the job is done
-// because we already got all the escape codes, so we only have to reinit.
-void ppmc_flush_mem_dec(void)
-{
-
- // Free memory and reinit
-
- ppmc_free_memory();
- ppmc_alloc_memory();
- ppmc_initialize_contexts();
-
-
- // Be sure that order-0 has at least one probability
-
- order0_array[o1_byte]++;
- order0_max_cump++;
- order0_defined_bytes++;
-
-
-}
-
-
-
-// ORDER-(-1) functions, also called ordern1 (Negative1) in functions
-//
-// Because order-(-1) does not need to update its probability tables, it
-// has no tables, and relies on the fact that the cump of byte is its own
-// value, and the probability is fixed, 1, and the total cump is 257.
-//
-// The alphabet has the following distribution: 0-255 the bytes. 256 is
-// an special symbol which means that we have flushed the encoder tables,
-// and thus the encoder must flush its tables too.
-//
-// The rest of the tables only have 256 symbols, because we have no need
-// of assign a symbol to the flush code (which already is the order-(-1)
-// table) nor to the escape code.
-
-
-// Gets the probability for a given symbol in the order-(-1) (ordern1)
-void ppmc_get_prob_ordern1(void)
-{
- int i;
- unsigned acum = 0;
- for (i = 0; i < 256 || i == byte; ++i)
- acum += ordern1_table[i];
- symb_cump=acum;
- symb_prob=ordern1_table[i];
- total_cump=ordern1_total_cump;
-}
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-(-1)
-void ppmc_get_totf_ordern1(void)
-{
- total_cump=ordern1_total_cump;
-}
-
-
-// Returns the symbol for a given cump under order-(-1)
-unsigned long ppmc_get_symbol_ordern1 (void)
-{
- return symb_cump;
-}
-
-
-
-// ORDER-0 functions
-//
-// Due to the fact that order-0 has no context, I use an array for all the
-// probabilities under order-0, just as you could do in a basic model for
-// arithmetic coding.
-//
-// The main array is: order0_array. Where order0_array[byte] contains the
-// probability for a given byte. The same applies to order-1.
-//
-// To ensure that the updating and coding is done correctly, "byte" can't
-// be changed till all the coding and updating is done.
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-0
-void ppmc_get_totf_order0(void)
-{
- // Total cump is current total cump plus the escape for the escape code
- total_cump=order0_defined_bytes+order0_max_cump;
-}
-
-
-// Codes a byte under order-0 and returns 1, otherwise it returns a 0 and
-// has coded an escape code. In this case further coding is needed.
-//
-// Returns: 1 in case a byte was coded. 0 in case of escape code.
-char ppmc_code_byte_order0(void)
-{
- unsigned long counter;
-
- ppmc_get_totf_order0(); //get total cump
-
- // See if the byte is present
- if(order0_array[byte]==0) //a probability of 0
- {
-
- // Because it was not present, output an escape code, prepare variables
-
- symb_cump=order0_max_cump; //obviously its cump is current max_cump
- //without escape code's space
-
- symb_prob=order0_defined_bytes; //the number of defined bytes
-
- // Code the escape code
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 0; //byte not coded
- }
- else
- {
-
- coded_in_order=0;
-
- // The symbol is present, code it under order-0
-
- symb_prob=order0_array[byte]; //get probability directly
-
- // Make cump for current symbol
-
- symb_cump=0; //for first symbol is 0
- for(counter=0; counter!=byte ; ++counter)
- symb_cump+=order0_array[counter]; //sum probabilities before our symbol
-
- // Code the symbol
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 1; //symbol coded under order-0
- }
-}
-
-
-// This functions update order-0 probabilities with current byte, also takes
-// care about updating variables, and renormalizing.
-void ppmc_update_order0(void)
-{
- if(order0_array[byte]==0)
- {
- // It had a zero probability
- order0_array[byte]++; //increment symbol probability
- ++order0_defined_bytes; //new byte defined
- ++order0_max_cump; //total cump
- return;
- }
- else
- {
- // It had a non-zero probability
-
- // Increment its probability
- order0_array[byte]++; //increment symbol probability
- ++order0_max_cump; //total cump
-
- // Check to see if its the maximum in this case renormalize
- if(order0_array[byte]==255)
- ppmc_renormalize_order0();
-
- return;
- }
-}
-
-
-// This functions renormalizes the probabilities at order-0 updating variables
-void ppmc_renormalize_order0(void)
-{
- unsigned long counter;
-
- // Initialize variables
- order0_defined_bytes=0; //clear them
- order0_max_cump=0;
-
- // Loop over all probabilities, divide them by a factor of 2 and update variables
- for(counter=0 ; counter!=256 ; ++counter)
- {
- order0_array[counter]>>=1; //divide by a factor of 2
-
- if(order0_array[counter]!=0) //see if it has a non zero probability
- order0_defined_bytes++;
-
- order0_max_cump+=order0_array[counter]; //sum to the total cump
- }
-}
-
-
-// Decodes the symbol correspoding to the current order, it returns the byte
-// or in case of a escape code it returns -1
-void ppmc_decode_order0(void)
-{
- unsigned long current_cump, counter;
-
-
- // Get the total cump needed for decoding symbol
- ppmc_get_totf_order0(); //total cump needed for decoding
- symb_cump=range_decoder_decode(&rc_decoder,total_cump); //decode it
-
- // Now check if it's an escape code
- if(symb_cump>=order0_max_cump) //the defined code space for the escape code
- {
-
- // Update coding values
-
- ppmc_get_escape_prob_order0();
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Mark as escape code
-
- byte=-1;
-
- return; //an escape code
- }
- else
- {
- // Now we have to check what symbol it is
-
- current_cump=0; //cump of the current symbol
-
- for(counter=0 ; counter!= 256 ; ++counter)
- {
- if(symb_cump<current_cump)
- break; //symbol found, break search loop
- current_cump+=order0_array[counter]; //update cump
- }
-
- counter--; //-1 (see ac_ppmc.html, searching for a given symbol)
-
- byte=counter; //update the variable with the found symbol
-
-
- // Get the cump and prob of byte
-
- symb_prob=order0_array[byte]; //the probabilty
- symb_cump=current_cump-order0_array[byte]; //using the cump which was
- //already made
-
- // Update coding state
-
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- coded_in_order=0; //decoded under order-0
-
- return;
- }
-
-}
-
-
-// This function returns the probability for the escape codes in the variables
-void ppmc_get_escape_prob_order0(void)
-{
- // To understand that remember that the escape allocated for the escape code
- // is above the current maximum cump and that it has a probability determined
- // by the scheme C.
- symb_prob=order0_defined_bytes;
- symb_cump=order0_max_cump;
- total_cump=order0_defined_bytes+order0_max_cump;
-}
-
-
-
-// ORDER-1 functions
-//
-// Order-1 uses 256 arrays one for every context, obviously they are accessed
-// like that: order1_array[o1_byte][byte]
-//
-// Also for computing the value of the current escape code in a given context
-// we need to know how many bytes are defined in a given context, they are
-// stored in an array, and you use them like that:
-// order1_defined_bytes_array[o1_byte]
-//
-// The same goes for the maximum cump of a given context:
-// order1_max_cump_array[o1_byte]
-//
-// Read the order-0 explanation.
-//
-// To ensure that the updating and coding is done correctly, "byte" and
-// "o1_byte" can't be changed till all the coding and updating is done.
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-1. o1_byte should contain the order-1
-void ppmc_get_totf_order1(void)
-{
- // Total cump is current total cump plus the escape for the escape code
- total_cump=order1_defined_bytes_array[o1_byte]+order1_max_cump_array[o1_byte];
-}
-
-
-// Codes a byte under order-1 and returns 1.
-// Otherwise it returns a 0 it may be that it has coded an escape code, or
-// that current table was empty, in this case nothing is outputted
-// In both cases further coding is needed.
-//
-// Returns: 1 in case a byte was coded. 0 in case of escape code or empty table.
-// In case the byte is coded under this context, coded_in_order=1.
-char ppmc_code_byte_order1(void)
-{
- unsigned long counter;
-
-
- // First check if current order-1 table is empty
- if(order1_defined_bytes_array[o1_byte]==0) //it's empty
- {
- return 0; //byte not coded, nothing done
- }
-
-
- // Now try to code this byte under order-1
-
- ppmc_get_totf_order1(); //get total cump
-
- // See if the byte is present
- if(order1_array[o1_byte][byte]==0) //a probability of 0
- {
-
- // Because it was not present, output an escape code, prepare variables
-
- symb_cump=order1_max_cump_array[o1_byte];//obviously its cump is current max_cump
- //without escape code's space
-
- symb_prob=order1_defined_bytes_array[o1_byte];//the number of defined bytes
-
- // Code the escape code
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 0; //byte not coded, escape coded
- }
- else
- {
-
- coded_in_order=1; //because we coded it under order-1
-
- // The symbol is present, code it under order-1
-
- symb_prob=order1_array[o1_byte][byte]; //get probability directly
-
- // Make cump for current symbol
-
- symb_cump=0; //for first symbol is 0
- for(counter=0; counter!=byte ; ++counter)
- symb_cump+=order1_array[o1_byte][counter]; //sum probabilities before our symbol
-
- // Code the symbol
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 1; //symbol coded under order-1
- }
-}
-
-
-// This functions update order-1 probabilities with current byte, also takes
-// care about updating variables, and renormalizing. o1_byte must be filled.
-void ppmc_update_order1(void)
-{
- if(order1_array[o1_byte][byte]==0)
- {
- // It had a zero probability
- order1_array[o1_byte][byte]++; //increment symbol probability
- ++order1_defined_bytes_array[o1_byte]; //new byte defined
- ++order1_max_cump_array[o1_byte]; //total cump
- return;
- }
- else
- {
- // It had a non-zero probability
-
- // Increment its probability
- order1_array[o1_byte][byte]++; //increment symbol probability
- ++order1_max_cump_array[o1_byte]; //total cump
-
- // Check to see if its the maximum in this case renormalize
- if(order1_array[o1_byte][byte]==255)
- ppmc_renormalize_order1();
-
- return;
- }
-}
-
-
-// This functions renormalizes the probabilities at order-1 updating variables
-void ppmc_renormalize_order1(void)
-{
- unsigned long counter;
-
- // Initialize variables
- order1_defined_bytes_array[o1_byte]=0; //clear them
- order1_max_cump_array[o1_byte]=0;
-
- // Loop over all probabilities, divide them by a factor of 2 and update variables
- for(counter=0 ; counter!=256 ; ++counter)
- {
- order1_array[o1_byte][counter]>>=1; //divide by a factor of 2
-
- if(order1_array[o1_byte][counter]!=0) //see if it has a non zero probability
- order1_defined_bytes_array[o1_byte]++;
-
- order1_max_cump_array[o1_byte]+=order1_array[o1_byte][counter]; //sum to the total cump
- }
-}
-
-
-// Decodes the symbol correspoding to the current order, it returns the byte
-// or in case of an escape code or empty table it returns -1.
-// It updates "coded_in_order".
-void ppmc_decode_order1(void)
-{
- unsigned long current_cump, counter;
-
-
- // First check if current order-1 table is empty
- if(order1_defined_bytes_array[o1_byte]==0) //it's empty
- {
- byte=-1; //byte not coded, nothing done
- return;
- }
-
-
- // Get the total cump needed for decoding symbol
- ppmc_get_totf_order1(); //total cump needed for decoding
- symb_cump=range_decoder_decode(&rc_decoder,total_cump); //decode it
-
- // Now check if it's an escape code
- if(symb_cump>=order1_max_cump_array[o1_byte]) //the defined code space for the escape code
- {
-
- // Update coding values
-
- ppmc_get_escape_prob_order1();
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Mark as escape code
-
- byte=-1;
-
- return; //an escape code
- }
- else
- {
- // Now we have to check what symbol it is
-
- current_cump=0; //cump of the current symbol
-
- for(counter=0 ; counter!= 256 ; ++counter)
- {
- if(symb_cump<current_cump)
- break; //symbol found, break search loop
- current_cump+=order1_array[o1_byte][counter]; //update cump
- }
-
- counter--; //-1 (see ac_ppmc.html, searching for a given symbol)
-
- byte=counter; //update the variable with the found symbol
-
-
- // Get the cump and prob of byte
-
- symb_prob=order1_array[o1_byte][byte]; //the probabilty
- symb_cump=current_cump-order1_array[o1_byte][byte]; //using the cump which was
- //already made
-
- // Update coding state
-
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
-
- // Update coded_in_order used for update exclusion
-
- coded_in_order=1;
-
- return;
- }
-
-}
-
-
-// This function returns the probability for the escape codes in the variables
-void ppmc_get_escape_prob_order1(void)
-{
- // To understand that remember that the escape allocated for the escape code
- // is above the current maximum cump and that it has a probability determined
- // by the scheme C.
- symb_prob=order1_defined_bytes_array[o1_byte];
- symb_cump=order1_max_cump_array[o1_byte];
- total_cump=order1_defined_bytes_array[o1_byte]+order1_max_cump_array[o1_byte];
-}
-
-
-
-// ORDER-2 functions
-//
-// Order-2 uses a table which holds the contexts data structure of every
-// structure, its accessed with "ppmc_order2_hash_key(o1_byte, o2_byte)"
-// and because it uses direct addressing there's no need to check for hash
-// collisions, which makes it faster. The variable "o2_cntxt" contains o1_byte
-// and o2_byte used directly to index the order-2 array.
-//
-// Though order-2 uses the same routines as lower orders they are rather
-// different, because we can't allocate memory for all the probabilities
-// tables, we have to use linked lists for the bytes and probabilities.
-//
-// Under order-2 we don't let a probability to be lower than 1, that is,
-// there can't be a symbol in a linked list with a 0 probability, I choosed
-// this for three factors: the code is easier to read (it isn't messy)
-// we gain some speed, and the loss of compression seems little.
-//
-// To ensure that the updating is done correctly, "o2_cntxt" and
-// "o2_ll_node" must not be modified by any routine except those who manage
-// order-2.
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-2. cntxt must have o1_byte and o2_byte hashed with the hash key
-// for order-2.
-void ppmc_get_totf_order2(void)
-{
- // Total cump is current total cump plus the escape for the escape code
- total_cump=order2_array[o2_cntxt].defined_bytes+order2_array[o2_cntxt].max_cump;
-}
-
-
-// Codes a byte under order-2 and returns 1.
-// Otherwise it returns a 0. It may be that it has coded an escape code, or
-// that current table was empty.
-//
-// Returns: 1 in case a byte was coded. 0 in case of escape code or empty table.
-// In case the byte is coded under this context, coded_in_order=2.
-char ppmc_code_byte_order2(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
-
- // Initialize o2_cntxt
-
- o2_cntxt=ppmc_order2_hash_key(o1_byte,o2_byte);
-
-
- // First check if current order-2 context is empty
- if(order2_array[o2_cntxt].defined_bytes==0) //it's empty
- {
- return 0; //byte not coded, nothing done
- }
-
-
- // Now try to code this byte under order-2
-
- ppmc_get_totf_order2(); //get total cump
-
-
- // See if the byte is present and compute its cump at the same time
-
- node=order2_array[o2_cntxt].prob; //pointer to first element in the linked list
-
- symb_cump=0; //the first symbol always has a 0 cump
-
-
- // Now search the byte in the linked list
-
- do{
- if(node->byte==byte)
- goto ppmc_o2_byte_found; //bad thing, I know, anyone has a better idea?
- symb_cump+=node->freq; //add the probability of this byte to the cump
- if(node->next==0)
- break;
- node=node->next; //next element in the linked list
- }while(1);
-
-
- // If we reach that point, the byte was not found in the linked list
- // so we don't need the cump, we have to output an escape code, whose
- // probabilities are know using the context structure in the table.
-
- // Byte was not present in the linked list, current node is the last one,
- // and that's the node needed for creating a new node, save it.
-
- o2_ll_node=node;
-
- // Now get the probability and cump of the escape code
-
- symb_cump=order2_array[o2_cntxt].max_cump;
- symb_prob=order2_array[o2_cntxt].defined_bytes;
-
- // Code the escape code
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 0;
-
-
- // That code is executed when the byte is found in the linked list
-
-ppmc_o2_byte_found:
-
-
- // Everything has been tested, now we can feel free to code the byte,
- // the symb_cump is already computed, now get its probability and code
- // the byte, also save pointer to this element in the linked lists for
- // updating.
-
- coded_in_order=2; //successfully coded under order-2
-
- o2_ll_node=node; //save it for updating
-
- symb_prob=node->freq; //get the probability of the byte
-
- // Code it.
-
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 1; //byte coded under order-2
-}
-
-
-// This functions update order-2 probabilities with current byte, also takes
-// care about updating variables, and renormalizing.
-// Of course "o2_ll_node" must point to the element to update or the last one,
-// based on the "coded_in_order" and checking the pointer of the element we
-// can decide what to do.
-//
-// This updating is only for encoding.
-void ppmc_update_order2(void)
-{
-
- // First of all check if that's the first byte in this context, in that case
- // we have to initialize some variables in the context structure.
-
- if(order2_array[o2_cntxt].defined_bytes==0) //no byte defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
- order2_array[o2_cntxt].defined_bytes=1;
- order2_array[o2_cntxt].max_cump=1;
- order2_array[o2_cntxt].prob=_bytes_pool;
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //nothing else to do
- }
-
-
- // The byte was coded under order two, otherwise it was coded under a
- // lower order (never higher ones, remember that we are using update
- // exclusion) in this case we have to create a new node in the list.
-
- if(coded_in_order==2) //coded under order-2
- {
-
- // Update its count and variables of this context and check for renormalization
-
- o2_ll_node->freq++; //increment its frequency (rather probability)
-
- order2_array[o2_cntxt].max_cump++; //total cump
-
- if(o2_ll_node->freq==255) //do we have to renormalize?
- ppmc_renormalize_order2(); //renormalize
-
- }
- else
- {
-
- // Once every paranoid check has been done we are sure that this byte
- // did not existed and so we have to create a new node in the linked
- // list. Also we have to take care of memory issues.
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- o2_ll_node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- order2_array[o2_cntxt].max_cump++; //total cump
- order2_array[o2_cntxt].defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- }
-
-}
-
-
-// This functions renormalizes the probabilities at order-2 updating context
-// variables.
-void ppmc_renormalize_order2(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
- // Initialize variables. Defined bytes remain the same.
- order2_array[o2_cntxt].max_cump=0; //clear them
-
- node=order2_array[o2_cntxt].prob; //get pointer to lined lists
-
- // Divide all the probabilities by 2 and update context variables
- while(1)
- {
- node->freq>>=1; //divide by a factor of 2
-
- if(node->freq==0) //don't allow a probability to be 0
- node->freq=1;
-
- order2_array[o2_cntxt].max_cump+=node->freq; //sum to the total cump
-
- if(node->next==0) //last element
- break;
- node=node->next;
- }
-
-
- //printf("\nRenormalization, context:%c%c",o2_byte,o1_byte);
-
-}
-
-
-// Decodes the symbol correspoding to the current order, it returns the byte
-// or in case of an escape code or empty table it returns -1.
-// It updates "coded_in_order".
-//
-// If we decode an escape code, we don't modify "o2_ll_node" and thus its
-// work of the updating routine to read till the end of the linked list
-// (for adding a new element) however if we decode a byte, we save on
-// "o2_ll_node" the pointer to its node. (so updating is faster)
-void ppmc_decode_order2(void)
-{
- unsigned long current_cump, counter;
- struct _byte_and_freq *node;
-
- // Initialize o2_cntxt
-
- o2_cntxt=ppmc_order2_hash_key(o1_byte,o2_byte);
-
-
- // First check if current order-2 context is empty
- if(order2_array[o2_cntxt].defined_bytes==0) //it's empty
- {
- byte=-1; //byte not coded, nothing done
- return;
- }
-
-
- // Get the total cump needed for decoding symbol
- ppmc_get_totf_order2(); //total cump needed for decoding
- symb_cump=range_decoder_decode(&rc_decoder,total_cump); //decode it
-
- // Now check if it's an escape code
- if(symb_cump>=order2_array[o2_cntxt].max_cump) //the defined code space for the escape code
- {
-
- // Update coding values
-
- ppmc_get_escape_prob_order2();
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Mark as escape code
-
- byte=-1;
-
- return; //an escape code
- }
- else
- {
- // Now we have to check what symbol it is
-
- current_cump=0; //cump of the current symbol
-
- node=order2_array[o2_cntxt].prob; //get pointer to linked lists
-
- while(1)
- {
- current_cump+=node->freq; //update cump
- if(symb_cump<current_cump)
- break; //symbol found, break search loop
-
- node=node->next; //next element
- //we have no need to check for the last symbol, we'll never read further
- //the end of the linked lists, before we'll found the last byte.
- }
-
-
- //read byte value and probability
-
- symb_prob=node->freq; //get the probability for updating the state
- byte=node->byte; //get byte
- o2_ll_node=node; //used for updating
-
-
- // Get the cump of byte
-
- symb_cump=current_cump-symb_prob;
-
- // Update coding state
-
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Update coded_in_order used for update exclusion
-
- coded_in_order=2;
-
- return;
- }
-
-}
-
-
-// This is the routine for updating while decoding. We have to search the byte
-// in the linked list, if it's present, update its count, otherwise we have
-// hitted the end of the linked list, and there we have to create a new node.
-//
-// Of course if the byte was matched in order-2 we'll have a pointer to it
-// in "o2_ll_node" so we don't need to read the linked list. (we already did
-// in decoding)
-//
-// Another case which we also have to specially deal with, this is the case
-// when the context has not been initalized yet.
-void ppmc_update_dec_order2(void)
-{
- struct _byte_and_freq *node;
-
-
- // Handle the case when the context is not initialized
- // This code is the same as the one for the encoding.
-
- if(order2_array[o2_cntxt].defined_bytes==0) //no byte defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
- order2_array[o2_cntxt].defined_bytes=1;
- order2_array[o2_cntxt].max_cump=1;
- order2_array[o2_cntxt].prob=_bytes_pool;
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
-
- return; //nothing else to do
- }
-
-
- // Current context is initalized, proceed
-
- if(coded_in_order==2) //check if it was decoded under order-2
- {
-
- // We can be sure that the pointer "o2_ll_node" points to its entry, and
- // it has a non 0 probability (otherwise it couldn't be coded) so just
- // update its probability and max_cump
-
- o2_ll_node->freq++; //the probability of the byte
- order2_array[o2_cntxt].max_cump++; //the max_cump
-
- if(o2_ll_node->freq==255) //check for renormalization
- ppmc_renormalize_order2();
-
- }
- else
- {
-
- // An escape code was decoded under order-2, we have to read till the
- // end of the linked list so we can add a new node for this new byte.
-
- node=order2_array[o2_cntxt].prob; //get pointer to linked list
-
- while(1)
- {
- if(node->next==0) //check for the end of the linked list
- break;
- node=node->next; //next node
- }
-
-
- // We reached the end of the linked list, add a new node if possible,
- // we are using the same code of "ppmc_update_order2()" with the
- // difference that the pointer to the linked list is "node"
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- order2_array[o2_cntxt].max_cump++; //total cump
- order2_array[o2_cntxt].defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //we are finished updating
-
- }
-
-}
-
-
-// This function returns the probability for the escape codes in the variables
-void ppmc_get_escape_prob_order2(void)
-{
- // To understand that remember that the escape allocated for the escape code
- // is above the current maximum cump and that it has a probability determined
- // by the scheme C.
-
- symb_prob=order2_array[o2_cntxt].defined_bytes;
- symb_cump=order2_array[o2_cntxt].max_cump;
-}
-
-
-
-// ORDER-3 functions
-//
-// The difference between order-3 and order-3 are just a few, instead of
-// keeping a table with the context structures, we keep a hash table with
-// pointers to linked lists with the context, so it's only a matter of
-// searching current context in the linked list corresponding to its hash
-// entry. This is done in "ppmc_get_totf_order3" because that's the first
-// routine that both encoding and decoding routines call.
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-3. Must be called while encoding or decoding before anything else
-// because it initializes the pointers to the context structure in
-// "o3_context" and o3_cntxt.
-//
-// If the hash entry is not initialized it returns "o3_context"=0
-// If the context is not present in the linked list of context, "o3_context"
-// will point to the last element in the linked list.
-// If the context is present "o3_context" will point to the context to use.
-// One can distinguish the last two by checking the context value of the
-// structure, if it's not the same, is the last element.
-//
-// The routine returns 0 if the hash entry is not initialized or if the
-// the context was not present. Otherwise it returns 1, meaning that we
-// have to code under this context.
-char ppmc_get_totf_order3(void)
-{
- struct context *cntxt_node;
-
-
- // First make the hash key for order-3
-
- o3_cntxt=ppmc_order3_hash_key(o1_byte,o2_byte,o3_byte);
- full_o3_cntxt=(o1_byte)+(o2_byte<<8)+(o3_byte<<16); //order-3
-
-
- // Now check the hash entry in the table
-
- if(order3_hasht[o3_cntxt]==0) //if 0, not initialized
- {
-
- o3_context=0; //no hash entry
-
- return 0; //hash entry not initialized
- }
-
-
- // Now read trough the linked list of context searching current one
-
- cntxt_node=order3_hasht[o3_cntxt];
-
- while(1)
- {
-
- if(cntxt_node->order4321==full_o3_cntxt) //compare context
- goto ppmc_gtf_cntxt_found;
-
- if(cntxt_node->next==0) //end of context's linked list
- break;
-
- cntxt_node=cntxt_node->next; //next element
-
- }
-
-
- // Once there the context was not found
- o3_context=cntxt_node; //pointer to last element in the linked list
-
- return 0; //it was not present
-
-
- // The context is found, so return pointer and cump
-
-ppmc_gtf_cntxt_found:
-
- o3_context=cntxt_node;
-
- // Total cump is current total cump plus the escape for the escape code
-
- total_cump=o3_context->defined_bytes+o3_context->max_cump;
-
- return 1; //context found
-
-}
-
-
-// Codes a byte under order-3 and returns 1.
-// Otherwise it returns a 0.
-//
-// In case the byte is coded under this context, coded_in_order=3.
-char ppmc_code_byte_order3(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
-
- // Get current context (if present) and total cump.
-
- if(ppmc_get_totf_order3()==0)
- return 0;
-
-
- // See if the byte is present and compute its cump at the same time
-
- node=o3_context->prob; //pointer to first element in the linked list
-
- symb_cump=0; //the first symbol always has a 0 cump
-
-
- // Now search the byte in the linked list
-
- do{
- if(node->byte==byte)
- goto ppmc_o3_byte_found; //bad thing, I know, anyone has a better idea?
- symb_cump+=node->freq; //add the probability of this byte to the cump
- if(node->next==0)
- break;
- node=node->next; //next element in the linked list
- }while(1);
-
-
- // If we reach that point, the byte was not found in the linked list
- // so we don't need the cump, we have to output an escape code, whose
- // probabilities are know using the context structure in the table.
-
- // Byte was not present in the linked list, current node is the last one,
- // and that's the node needed for creating a new node, save it.
-
- o3_ll_node=node;
-
- // Now get the probability and cump of the escape code
-
- symb_cump=o3_context->max_cump;
- symb_prob=o3_context->defined_bytes;
-
- // Code the escape code
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 0;
-
-
- // That code is executed when the byte is found in the linked list
-
-ppmc_o3_byte_found:
-
-
- // Everything has been tested, now we can feel free to code the byte,
- // the symb_cump is already computed, now get its probability and code
- // the byte, also save pointer to this element in the linked lists for
- // updating.
-
- coded_in_order=3; //successfully coded under order-3
-
- o3_ll_node=node; //save it for updating
-
- symb_prob=node->freq; //get the probability of the byte
-
- // Code it.
-
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 1; //byte coded under order-3
-}
-
-
-// This functions update order-3 probabilities with current byte, also takes
-// care about updating variables, and renormalizing.
-//
-// "o3_ll_node" must point to the element to update or the last one,
-// based on the "coded_in_order" and checking the pointer of the element we
-// can decide what to do. Also "o3_context" must be initialized.
-//
-// This updating is only for encoding.
-void ppmc_update_order3(void)
-{
-
- // First thing first, check if the hash entry is initialized
-
- if(order3_hasht[o3_cntxt]==0) //no pointer to linked list defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- order3_hasht[o3_cntxt]=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o3_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //nothing else to do
- }
-
-
-
-
- // The byte was coded under order three, otherwise it was coded under a
- // lower order (never higher ones, remember that we are using update
- // exclusion) in this case we have to create a new node in the list.
-
- if(coded_in_order==3) //coded under order-3
- {
-
- // Update its count and variables of this context and check for renormalization
-
- o3_ll_node->freq++; //increment its frequency (rather probability)
-
- o3_context->max_cump++; //total cump
-
- if(o3_ll_node->freq==255) //do we have to renormalize?
- ppmc_renormalize_order3(); //renormalize
-
- }
- else
- {
-
- // Now we have two cases, under a given context (which we actually found)
- // we coded an escape coded, in that case just create a new node in the
- // linked list of bytes and probabilities. Otherwise we didn't find the
- // same node so we have to create it in the linked list for context.
- // And we can be sure that it at least has one element and that
- // "o3_context" points to the last element, so we can put the new element.
-
- if(o3_context->order4321==full_o3_cntxt) //chech if that's the last
- { //element or the a context found
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- o3_ll_node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- o3_context->max_cump++; //total cump
- o3_context->defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
- }
- else
- {
-
- // We have to create a new context node
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- o3_context->next=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o3_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- }
-
- }
-
-}
-
-
-// This functions renormalizes the probabilities at order-3 updating context
-// variables.
-void ppmc_renormalize_order3(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
-
- // Initialize variables. Defined bytes remain the same.
- o3_context->max_cump=0; //clear them
-
- node=o3_context->prob; //get pointer to lined lists
-
- // Divide all the probabilities by 2 and update context variables
- while(1)
- {
- node->freq>>=1; //divide by a factor of 2
-
- if(node->freq==0) //don't allow a probability to be 0
- node->freq=1;
-
- o3_context->max_cump+=node->freq; //sum to the total cump
-
- if(node->next==0) //last element
- break;
- node=node->next;
- }
-
-
-}
-
-
-// Decodes the symbol correspoding to the current order, it returns the byte
-// or in case of an escape code or empty table it returns -1.
-// It updates "coded_in_order".
-//
-// If we decode an escape code, we don't modify "o3_ll_node" and thus its
-// work of the updating routine to read till the end of the linked list
-// (for adding a new element) however if we decode a byte, we save on
-// "o3_ll_node" the pointer to its node. (so updating is faster)
-void ppmc_decode_order3(void)
-{
- unsigned long current_cump, counter;
- struct _byte_and_freq *node;
-
-
- // Get current context (if present) and total cump.
-
- if(ppmc_get_totf_order3()==0)
- {
- byte=-1;
- return;
- }
-
-
- // Decode current cump
-
- symb_cump=range_decoder_decode(&rc_decoder,total_cump); //decode it
-
- // Now check if it's an escape code
- if(symb_cump>=o3_context->max_cump) //the defined code space for the escape code
- {
-
- // Update coding values
-
- ppmc_get_escape_prob_order3();
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Mark as escape code
-
- byte=-1;
-
- return; //an escape code
- }
- else
- {
- // Now we have to check what symbol it is
-
- current_cump=0; //cump of the current symbol
-
- node=o3_context->prob; //get pointer to linked lists
-
- while(1)
- {
- current_cump+=node->freq; //update cump
- if(symb_cump<current_cump)
- break; //symbol found, break search loop
-
- node=node->next; //next element
- //we have no need to check for the last symbol, we'll never read further
- //the end of the linked lists, before we'll found the last byte.
- }
-
-
- //read byte value and probability
-
- symb_prob=node->freq; //get the probability for updating the state
- byte=node->byte; //get byte
- o3_ll_node=node; //used for updating
-
-
- // Get the cump of byte
-
- symb_cump=current_cump-symb_prob;
-
- // Update coding state
-
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Update coded_in_order used for update exclusion
-
- coded_in_order=3;
-
- return;
- }
-
-}
-
-
-// This is the routine for updating while decoding. The only difference with
-// the routine for coding is that when an escape code was coded, "o3_ll_node"
-// is not initialized so we have to read till the end of the linked list.
-// Fortunately "o3_context" will be initialized so we don't need to read its
-// linked list.
-void ppmc_update_dec_order3(void)
-{
- struct _byte_and_freq *node;
-
- // First thing first, check if the hash entry is initialized
-
- if(order3_hasht[o3_cntxt]==0) //no pointer to linked list defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- order3_hasht[o3_cntxt]=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o3_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //nothing else to do
- }
-
-
- // The byte was coded under order three, otherwise it was coded under a
- // lower order (never higher ones, remember that we are using update
- // exclusion) in this case we have to create a new node in the list.
-
- if(coded_in_order==3) //coded under order-3
- {
-
- // Update its count and variables of this context and check for renormalization
-
- o3_ll_node->freq++; //increment its frequency (rather probability)
-
- o3_context->max_cump++; //total cump
-
- if(o3_ll_node->freq==255) //do we have to renormalize?
- ppmc_renormalize_order3(); //renormalize
-
- }
- else
- {
-
- // Now we have two cases, under a given context (which we actually found)
- // we coded an escape coded, in that case just create a new node in the
- // linked list of bytes and probabilities. Otherwise we didn't find the
- // same node so we have to create it in the linked list for context.
- // And we can be sure that it at least has one element and that
- // "o3_context" points to the last element, so we can put the new element.
-
- if(o3_context->order4321==full_o3_cntxt) //chech if that's the last
- { //element or the a context found
-
- // Read till the end of the linked list
-
- node=o3_context->prob; //get pointer to linked list
-
- while(1)
- {
- if(node->next==0) //check for the end of the linked list
- break;
- node=node->next; //next node
- }
-
- // Now add element
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- o3_context->max_cump++; //total cump
- o3_context->defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
- }
- else
- {
-
- // We have to create a new context node
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- o3_context->next=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o3_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- }
-
- }
-
-}
-
-
-
-// This function returns the probability for the escape codes in the variables
-void ppmc_get_escape_prob_order3(void)
-{
- // To understand that remember that the escape allocated for the escape code
- // is above the current maximum cump and that it has a probability determined
- // by the scheme C.
-
- symb_prob=o3_context->defined_bytes;
- symb_cump=o3_context->max_cump;
-}
-
-
-
-// ORDER-4 functions
-//
-// The routines for order-4 are *equal* to those for order-3, there are a few
-// changes like different global variables, and different hash keys.
-//
-// If you want to go to higher orders, you'd use the same code and data
-// structures, with the difference of the context bytes (order4321)
-// stored in every context's linked list.
-
-
-// Returns in the variable "total_cump" the current total cump of
-// order-4. Must be called while encoding or decoding before anything else
-// because it initializes the pointers to the context structure in
-// "o4_context" and o4_cntxt.
-//
-// If the hash entry is not initialized it returns "o4_context"=0
-// If the context is not present in the linked list of context, "o4_context"
-// will point to the last element in the linked list.
-// If the context is present "o4_context" will point to the context to use.
-// One can distinguish the last two by checking the context value of the
-// structure, if it's not the same, is the last element.
-//
-// The routine returns 0 if the hash entry is not initialized or if the
-// the context was not present. Otherwise it returns 1, meaning that we
-// have to code under this context.
-char ppmc_get_totf_order4(void)
-{
- struct context *cntxt_node;
-
-
- // First make the hash key for order-4
-
- o4_cntxt=ppmc_order4_hash_key(o1_byte,o2_byte,o3_byte,o4_byte);
- full_o4_cntxt=(o1_byte)+(o2_byte<<8)+(o3_byte<<16)+(o4_byte<<24); //order-4
-
-
- // Now check the hash entry in the table
-
- if(order4_hasht[o4_cntxt]==0) //if 0, not initialized
- {
-
- o4_context=0; //no hash entry
-
- return 0; //hash entry not initialized
- }
-
-
- // Now read trough the linked list of context searching current one
-
- cntxt_node=order4_hasht[o4_cntxt];
-
- while(1)
- {
-
- if(cntxt_node->order4321==full_o4_cntxt) //compare context
- goto ppmc_gtfo4_cntxt_found;
-
- if(cntxt_node->next==0) //end of context's linked list
- break;
-
- cntxt_node=cntxt_node->next; //next element
-
- }
-
-
- // Once there the context was not found
- o4_context=cntxt_node; //pointer to last element in the linked list
-
- return 0; //it was not present
-
-
- // The context is found, so return pointer and cump
-
-ppmc_gtfo4_cntxt_found:
-
- o4_context=cntxt_node;
-
- // Total cump is current total cump plus the escape for the escape code
-
- total_cump=o4_context->defined_bytes+o4_context->max_cump;
-
- return 1; //context found
-
-}
-
-
-// Codes a byte under order-4 and returns 1.
-// Otherwise it returns a 0.
-//
-// In case the byte is coded under this context, coded_in_order=4.
-char ppmc_code_byte_order4(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
-
- // Get current context (if present) and total cump.
-
- if(ppmc_get_totf_order4()==0)
- return 0;
-
-
- // See if the byte is present and compute its cump at the same time
-
- node=o4_context->prob; //pointer to first element in the linked list
-
- symb_cump=0; //the first symbol always has a 0 cump
-
-
- // Now search the byte in the linked list
-
- do{
- if(node->byte==byte)
- goto ppmc_o4_byte_found; //bad thing, I know, anyone has a better idea?
- symb_cump+=node->freq; //add the probability of this byte to the cump
- if(node->next==0)
- break;
- node=node->next; //next element in the linked list
- }while(1);
-
-
- // If we reach that point, the byte was not found in the linked list
- // so we don't need the cump, we have to output an escape code, whose
- // probabilities are know using the context structure in the table.
-
- // Byte was not present in the linked list, current node is the last one,
- // and that's the node needed for creating a new node, save it.
-
- o4_ll_node=node;
-
- // Now get the probability and cump of the escape code
-
- symb_cump=o4_context->max_cump;
- symb_prob=o4_context->defined_bytes;
-
- // Code the escape code
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 0;
-
-
- // That code is executed when the byte is found in the linked list
-
-ppmc_o4_byte_found:
-
-
- // Everything has been tested, now we can feel free to code the byte,
- // the symb_cump is already computed, now get its probability and code
- // the byte, also save pointer to this element in the linked lists for
- // updating.
-
- coded_in_order=4; //successfully coded under order-4
-
- o4_ll_node=node; //save it for updating
-
- symb_prob=node->freq; //get the probability of the byte
-
- // Code it.
-
- range_coder_encode(&rc_coder,total_cump,symb_cump,symb_prob);
-
- return 1; //byte coded under order-4
-}
-
-
-// This functions update order-4 probabilities with current byte, also takes
-// care about updating variables, and renormalizing.
-//
-// "o4_ll_node" must point to the element to update or the last one,
-// based on the "coded_in_order" and checking the pointer of the element we
-// can decide what to do. Also "o4_context" must be initialized.
-//
-// This updating is only for encoding.
-void ppmc_update_order4(void)
-{
-
- // First thing first, check if the hash entry is initialized
-
- if(order4_hasht[o4_cntxt]==0) //no pointer to linked list defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- order4_hasht[o4_cntxt]=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o4_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //nothing else to do
- }
-
-
-
-
- // The byte was coded under order three, otherwise it was coded under a
- // lower order (never higher ones, remember that we are using update
- // exclusion) in this case we have to create a new node in the list.
-
- if(coded_in_order==4) //coded under order-4
- {
-
- // Update its count and variables of this context and check for renormalization
-
- o4_ll_node->freq++; //increment its frequency (rather probability)
-
- o4_context->max_cump++; //total cump
-
- if(o4_ll_node->freq==255) //do we have to renormalize?
- ppmc_renormalize_order4(); //renormalize
-
- }
- else
- {
-
- // Now we have two cases, under a given context (which we actually found)
- // we coded an escape coded, in that case just create a new node in the
- // linked list of bytes and probabilities. Otherwise we didn't find the
- // same node so we have to create it in the linked list for context.
- // And we can be sure that it at least has one element and that
- // "o4_context" points to the last element, so we can put the new element.
-
- if(o4_context->order4321==full_o4_cntxt) //chech if that's the last
- { //element or the a context found
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- o4_ll_node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- o4_context->max_cump++; //total cump
- o4_context->defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
- }
- else
- {
-
- // We have to create a new context node
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- o4_context->next=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o4_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- }
-
- }
-
-}
-
-
-// This functions renormalizes the probabilities at order-4 updating context
-// variables.
-void ppmc_renormalize_order4(void)
-{
- unsigned long counter;
- struct _byte_and_freq *node;
-
-
- // Initialize variables. Defined bytes remain the same.
- o4_context->max_cump=0; //clear them
-
- node=o4_context->prob; //get pointer to lined lists
-
- // Divide all the probabilities by 2 and update context variables
- while(1)
- {
- node->freq>>=1; //divide by a factor of 2
-
- if(node->freq==0) //don't allow a probability to be 0
- node->freq=1;
-
- o4_context->max_cump+=node->freq; //sum to the total cump
-
- if(node->next==0) //last element
- break;
- node=node->next;
- }
-
-
-}
-
-
-// Decodes the symbol correspoding to the current order, it returns the byte
-// or in case of an escape code or empty table it returns -1.
-// It updates "coded_in_order".
-//
-// If we decode an escape code, we don't modify "o4_ll_node" and thus its
-// work of the updating routine to read till the end of the linked list
-// (for adding a new element) however if we decode a byte, we save on
-// "o4_ll_node" the pointer to its node. (so updating is faster)
-void ppmc_decode_order4(void)
-{
- unsigned long current_cump, counter;
- struct _byte_and_freq *node;
-
-
- // Get current context (if present) and total cump.
-
- if(ppmc_get_totf_order4()==0)
- {
- byte=-1;
- return;
- }
-
-
- // Decode current cump
-
- symb_cump=range_decoder_decode(&rc_decoder,total_cump); //decode it
-
- // Now check if it's an escape code
- if(symb_cump>=o4_context->max_cump) //the defined code space for the escape code
- {
-
- // Update coding values
-
- ppmc_get_escape_prob_order4();
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Mark as escape code
-
- byte=-1;
-
- return; //an escape code
- }
- else
- {
- // Now we have to check what symbol it is
-
- current_cump=0; //cump of the current symbol
-
- node=o4_context->prob; //get pointer to linked lists
-
- while(1)
- {
- current_cump+=node->freq; //update cump
- if(symb_cump<current_cump)
- break; //symbol found, break search loop
-
- node=node->next; //next element
- //we have no need to check for the last symbol, we'll never read further
- //the end of the linked lists, before we'll found the last byte.
- }
-
-
- //read byte value and probability
-
- symb_prob=node->freq; //get the probability for updating the state
- byte=node->byte; //get byte
- o4_ll_node=node; //used for updating
-
-
- // Get the cump of byte
-
- symb_cump=current_cump-symb_prob;
-
- // Update coding state
-
- range_decoder_update(&rc_decoder,total_cump,symb_cump,symb_prob);
-
- // Update coded_in_order used for update exclusion
-
- coded_in_order=4;
-
- return;
- }
-
-}
-
-
-// This is the routine for updating while decoding. The only difference with
-// the routine for coding is that when an escape code was coded, "o4_ll_node"
-// is not initialized so we have to read till the end of the linked list.
-// Fortunately "o4_context" will be initialized so we don't need to read its
-// linked list.
-void ppmc_update_dec_order4(void)
-{
- struct _byte_and_freq *node;
-
- // First thing first, check if the hash entry is initialized
-
- if(order4_hasht[o4_cntxt]==0) //no pointer to linked list defined yet
- {
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- order4_hasht[o4_cntxt]=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o4_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- return; //nothing else to do
- }
-
-
- // The byte was coded under order four, otherwise it was coded under a
- // lower order (never higher ones, remember that we are using update
- // exclusion) in this case we have to create a new node in the list.
-
- if(coded_in_order==4) //coded under order-4
- {
-
- // Update its count and variables of this context and check for renormalization
-
- o4_ll_node->freq++; //increment its frequency (rather probability)
-
- o4_context->max_cump++; //total cump
-
- if(o4_ll_node->freq==255) //do we have to renormalize?
- ppmc_renormalize_order4(); //renormalize
-
- }
- else
- {
-
- // Now we have two cases, under a given context (which we actually found)
- // we coded an escape coded, in that case just create a new node in the
- // linked list of bytes and probabilities. Otherwise we didn't find the
- // same node so we have to create it in the linked list for context.
- // And we can be sure that it at least has one element and that
- // "o4_context" points to the last element, so we can put the new element.
-
- if(o4_context->order4321==full_o4_cntxt) //chech if that's the last
- { //element or the a context found
-
- // Read till the end of the linked list
-
- node=o4_context->prob; //get pointer to linked list
-
- while(1)
- {
- if(node->next==0) //check for the end of the linked list
- break;
- node=node->next; //next node
- }
-
- // Now add element
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate mem
-
- node->next=_bytes_pool; //put it in the next free entry
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- o4_context->max_cump++; //total cump
- o4_context->defined_bytes++; //total cump
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
- }
- else
- {
-
- // We have to create a new context node
-
- if(ppmc_out_of_memory==1)
- return; //exit this function, we can't allocate memory
-
-
- // First create the context
-
- o4_context->next=_context_pool;
-
- _context_pool->next=0; //this is the last element
- _context_pool->order4321=full_o4_cntxt; //put context
- _context_pool->prob=_bytes_pool; //pointer to linked list
- _context_pool->max_cump=1;
- _context_pool->defined_bytes=1;
-
-
- // Do update of linked list variables and memory use of contexts
-
- ++_context_pool; //next time use next entry (this is a pointer)
-
- if(_context_pool==_context_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_context_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_context_pool=(struct context *)malloc
- (sizeof(struct context)*_context_pool_elements_inc))==NULL)
- {
- printf("Can't allocate memory for context's memory pool.\nIndex: %d",_context_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _context_pool_array[_context_pool_index]=_context_pool;
-
- _context_pool_max=_context_pool+_context_pool_elements_inc;
-
- _context_pool_index++;
-
- }
-
- // Now care about the first (and last) linked list element
-
- _bytes_pool->byte=byte; //initialize byte to current one
- _bytes_pool->freq=1; //it appeared once
- _bytes_pool->next=0; //now this is last element in ll
-
- // Do update of linked list variables and memory use
-
- ++_bytes_pool; //next time use next entry (this is a pointer)
-
- if(_bytes_pool==_bytes_pool_max) //maximum reached
- {
-
- // First check to see that we still have entries in the array
-
- if(_bytes_pool_index==_mempool_max_index)
- {
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- // Allocate memory for new buffer
-
- if((_bytes_pool=(struct _byte_and_freq *)malloc
- (sizeof(struct _byte_and_freq)*_bytes_pool_elements_inc))==NULL)
- {
- printf("\nCan't allocate memory for bytes memory pool.\nIndex: %d",_bytes_pool_index);
- ppmc_out_of_memory=1; //flush
- return;
- }
-
- _bytes_pool_array[_bytes_pool_index]=_bytes_pool;
-
- _bytes_pool_max=_bytes_pool+_bytes_pool_elements_inc;
-
- _bytes_pool_index++;
-
- }
-
- }
-
- }
-
-}
-
-
-
-// This function returns the probability for the escape codes in the variables
-void ppmc_get_escape_prob_order4(void)
-{
- // To understand that remember that the escape allocated for the escape code
- // is above the current maximum cump and that it has a probability determined
- // by the scheme C.
-
- symb_prob=o4_context->defined_bytes;
- symb_cump=o4_context->max_cump;
-}
-