elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [Source] Compresor mejor y mas rápido que FreeARC, en C.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [Source] Compresor mejor y mas rápido que FreeARC, en C.  (Leído 1,539 veces)
sabeeee

Desconectado Desconectado

Mensajes: 155


Ver Perfil
[Source] Compresor mejor y mas rápido que FreeARC, en C.
« en: 25 Febrero 2015, 23:04 pm »

Un regalo para ustedes que encontré por ahí  :rolleyes: después de tanta ayuda prestada, muchos ya lo deben conocer, es un derivado de PAQ8 ¿Se acuerdan del famoso KGB archiver?, bueno este código usa casi el mismo método pero es mucho mas rápido y funciono en mi Android con CppDroid. Excepto WAV (Tiene un algoritmo especial), es muy superior que FreeARC.

Uso:
Código:
paq9a a "saliente.paq9a" -0...9 "entrante.archivo"

Compilación:
Código:
@path C:\MinGw\bin;%path%
g++ -fpermissive -O3 -s paq9a.cpp -o paq9a
pause
Web (muy buena): http://mattmahoney.net/dc/
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <ctype.h>
  6. #define NDEBUG  // remove for debugging
  7. #include <assert.h>
  8.  
  9. int allocated=0;  // Total memory allocated by alloc()
  10.  
  11. // Create an array p of n elements of type T
  12. template <class T> void alloc(T*&p, int n) {
  13.  p=(T*)calloc(n, sizeof(T));
  14.  if (!p) printf("Out of memory\n"), exit(1);
  15.  allocated+=n*sizeof(T);
  16. }
  17.  
  18. // 8, 16, 32 bit unsigned types (adjust as appropriate)
  19. typedef unsigned char  U8;
  20. typedef unsigned short U16;
  21. typedef unsigned int   U32;
  22.  
  23. ///////////////////////////// Squash //////////////////////////////
  24.  
  25. // return p = 1/(1 + exp(-d)), d scaled by 8 bits, p scaled by 12 bits
  26. class Squash {
  27.  short t[4096];
  28. public:
  29.  Squash();
  30.  int operator()(int p) const {
  31.    if (p>2047) return 4095;
  32.  if (p<-2047) return 0;
  33.    return t[p+2048];
  34.  }
  35. } squash;
  36.  
  37. Squash::Squash() {
  38. int ts[33]={1,2,3,6,10,16,27,45,73,120,194,310,488,747,1101,
  39.    1546,2047,2549,2994,3348,3607,3785,3901,3975,4022,
  40.    4050,4068,4079,4085,4089,4092,4093,4094};
  41. int w,d;
  42.  for (int i=-2047; i<=2047; ++i){
  43.    w=i&127;
  44.    d=(i>>7)+16;
  45.    t[i+2048]=(ts[d]*(128-w)+ts[(d+1)]*w+64) >> 7;
  46.    }
  47. }
  48.  
  49. //////////////////////////// Stretch ///////////////////////////////
  50.  
  51. // Inverse of squash. stretch(d) returns ln(p/(1-p)), d scaled by 8 bits,
  52. // p by 12 bits.  d has range -2047 to 2047 representing -8 to 8.  
  53. // p has range 0 to 4095 representing 0 to 1.
  54.  
  55. class Stretch {
  56.  short t[4096];
  57. public:
  58.  Stretch();
  59.  int operator()(int p) const {
  60.    assert(p>=0 && p<4096);
  61.    return t[p];
  62.  }
  63. } stretch;
  64.  
  65. Stretch::Stretch() {
  66.  int pi=0;
  67.  for (int x=-2047; x<=2047; ++x) {  // invert squash()
  68.    int i=squash(x);
  69.    for (int j=pi; j<=i; ++j)
  70.      t[j]=x;
  71.    pi=i+1;
  72.  }
  73.  t[4095]=2047;
  74. }
  75.  
  76. ///////////////////////////// ilog //////////////////////////////
  77.  
  78. // ilog(x) = round(log2(x) * 16), 0 <= x < 64K
  79. class Ilog {
  80.  U8* t;
  81. public:
  82.  int operator()(U16 x) const {return t[x];}
  83.  Ilog();
  84. } ilog;
  85.  
  86. // Compute lookup table by numerical integration of 1/x
  87. Ilog::Ilog(): t(65536) {
  88.  U32 x=14155776;
  89.  for (int i=2; i<65536; ++i) {
  90.    x+=774541002/(i*2-1);  // numerator is 2^29/ln 2
  91.    t[i]=x>>24;
  92.  }
  93. }
  94.  
  95. // llog(x) accepts 32 bits
  96. inline int llog(U32 x) {
  97.  if (x>=0x1000000)
  98.    return 256+ilog(x>>16);
  99.  else if (x>=0x10000)
  100.    return 128+ilog(x>>8);
  101.  else
  102.    return ilog(x);
  103. }
  104.  
  105. ///////////////////////// state table ////////////////////////
  106.  
  107. // State table:
  108. //   nex(state, 0) = next state if bit y is 0, 0 <= state < 256
  109. //   nex(state, 1) = next state if bit y is 1
  110. //
  111. // States represent a bit history within some context.
  112. // State 0 is the starting state (no bits seen).
  113. // States 1-30 represent all possible sequences of 1-4 bits.
  114. // States 31-252 represent a pair of counts, (n0,n1), the number
  115. //   of 0 and 1 bits respectively.  If n0+n1 < 16 then there are
  116. //   two states for each pair, depending on if a 0 or 1 was the last
  117. //   bit seen.
  118. // If n0 and n1 are too large, then there is no state to represent this
  119. // pair, so another state with about the same ratio of n0/n1 is substituted.
  120. // Also, when a bit is observed and the count of the opposite bit is large,
  121. // then part of this count is discarded to favor newer data over old.
  122.  
  123. static const U8 State_table[256][4]={
  124.  {  1,  2, 0, 0},{  3,  5, 1, 0},{  4,  6, 0, 1},{  7, 10, 2, 0}, // 0-3
  125.  {  8, 12, 1, 1},{  9, 13, 1, 1},{ 11, 14, 0, 2},{ 15, 19, 3, 0}, // 4-7
  126.  { 16, 23, 2, 1},{ 17, 24, 2, 1},{ 18, 25, 2, 1},{ 20, 27, 1, 2}, // 8-11
  127.  { 21, 28, 1, 2},{ 22, 29, 1, 2},{ 26, 30, 0, 3},{ 31, 33, 4, 0}, // 12-15
  128.  { 32, 35, 3, 1},{ 32, 35, 3, 1},{ 32, 35, 3, 1},{ 32, 35, 3, 1}, // 16-19
  129.  { 34, 37, 2, 2},{ 34, 37, 2, 2},{ 34, 37, 2, 2},{ 34, 37, 2, 2}, // 20-23
  130.  { 34, 37, 2, 2},{ 34, 37, 2, 2},{ 36, 39, 1, 3},{ 36, 39, 1, 3}, // 24-27
  131.  { 36, 39, 1, 3},{ 36, 39, 1, 3},{ 38, 40, 0, 4},{ 41, 43, 5, 0}, // 28-31
  132.  { 42, 45, 4, 1},{ 42, 45, 4, 1},{ 44, 47, 3, 2},{ 44, 47, 3, 2}, // 32-35
  133.  { 46, 49, 2, 3},{ 46, 49, 2, 3},{ 48, 51, 1, 4},{ 48, 51, 1, 4}, // 36-39
  134.  { 50, 52, 0, 5},{ 53, 43, 6, 0},{ 54, 57, 5, 1},{ 54, 57, 5, 1}, // 40-43
  135.  { 56, 59, 4, 2},{ 56, 59, 4, 2},{ 58, 61, 3, 3},{ 58, 61, 3, 3}, // 44-47
  136.  { 60, 63, 2, 4},{ 60, 63, 2, 4},{ 62, 65, 1, 5},{ 62, 65, 1, 5}, // 48-51
  137.  { 50, 66, 0, 6},{ 67, 55, 7, 0},{ 68, 57, 6, 1},{ 68, 57, 6, 1}, // 52-55
  138.  { 70, 73, 5, 2},{ 70, 73, 5, 2},{ 72, 75, 4, 3},{ 72, 75, 4, 3}, // 56-59
  139.  { 74, 77, 3, 4},{ 74, 77, 3, 4},{ 76, 79, 2, 5},{ 76, 79, 2, 5}, // 60-63
  140.  { 62, 81, 1, 6},{ 62, 81, 1, 6},{ 64, 82, 0, 7},{ 83, 69, 8, 0}, // 64-67
  141.  { 84, 71, 7, 1},{ 84, 71, 7, 1},{ 86, 73, 6, 2},{ 86, 73, 6, 2}, // 68-71
  142.  { 44, 59, 5, 3},{ 44, 59, 5, 3},{ 58, 61, 4, 4},{ 58, 61, 4, 4}, // 72-75
  143.  { 60, 49, 3, 5},{ 60, 49, 3, 5},{ 76, 89, 2, 6},{ 76, 89, 2, 6}, // 76-79
  144.  { 78, 91, 1, 7},{ 78, 91, 1, 7},{ 80, 92, 0, 8},{ 93, 69, 9, 0}, // 80-83
  145.  { 94, 87, 8, 1},{ 94, 87, 8, 1},{ 96, 45, 7, 2},{ 96, 45, 7, 2}, // 84-87
  146.  { 48, 99, 2, 7},{ 48, 99, 2, 7},{ 88,101, 1, 8},{ 88,101, 1, 8}, // 88-91
  147.  { 80,102, 0, 9},{103, 69,10, 0},{104, 87, 9, 1},{104, 87, 9, 1}, // 92-95
  148.  {106, 57, 8, 2},{106, 57, 8, 2},{ 62,109, 2, 8},{ 62,109, 2, 8}, // 96-99
  149.  { 88,111, 1, 9},{ 88,111, 1, 9},{ 80,112, 0,10},{113, 85,11, 0}, // 100-103
  150.  {114, 87,10, 1},{114, 87,10, 1},{116, 57, 9, 2},{116, 57, 9, 2}, // 104-107
  151.  { 62,119, 2, 9},{ 62,119, 2, 9},{ 88,121, 1,10},{ 88,121, 1,10}, // 108-111
  152.  { 90,122, 0,11},{123, 85,12, 0},{124, 97,11, 1},{124, 97,11, 1}, // 112-115
  153.  {126, 57,10, 2},{126, 57,10, 2},{ 62,129, 2,10},{ 62,129, 2,10}, // 116-119
  154.  { 98,131, 1,11},{ 98,131, 1,11},{ 90,132, 0,12},{133, 85,13, 0}, // 120-123
  155.  {134, 97,12, 1},{134, 97,12, 1},{136, 57,11, 2},{136, 57,11, 2}, // 124-127
  156.  { 62,139, 2,11},{ 62,139, 2,11},{ 98,141, 1,12},{ 98,141, 1,12}, // 128-131
  157.  { 90,142, 0,13},{143, 95,14, 0},{144, 97,13, 1},{144, 97,13, 1}, // 132-135
  158.  { 68, 57,12, 2},{ 68, 57,12, 2},{ 62, 81, 2,12},{ 62, 81, 2,12}, // 136-139
  159.  { 98,147, 1,13},{ 98,147, 1,13},{100,148, 0,14},{149, 95,15, 0}, // 140-143
  160.  {150,107,14, 1},{150,107,14, 1},{108,151, 1,14},{108,151, 1,14}, // 144-147
  161.  {100,152, 0,15},{153, 95,16, 0},{154,107,15, 1},{108,155, 1,15}, // 148-151
  162.  {100,156, 0,16},{157, 95,17, 0},{158,107,16, 1},{108,159, 1,16}, // 152-155
  163.  {100,160, 0,17},{161,105,18, 0},{162,107,17, 1},{108,163, 1,17}, // 156-159
  164.  {110,164, 0,18},{165,105,19, 0},{166,117,18, 1},{118,167, 1,18}, // 160-163
  165.  {110,168, 0,19},{169,105,20, 0},{170,117,19, 1},{118,171, 1,19}, // 164-167
  166.  {110,172, 0,20},{173,105,21, 0},{174,117,20, 1},{118,175, 1,20}, // 168-171
  167.  {110,176, 0,21},{177,105,22, 0},{178,117,21, 1},{118,179, 1,21}, // 172-175
  168.  {110,180, 0,22},{181,115,23, 0},{182,117,22, 1},{118,183, 1,22}, // 176-179
  169.  {120,184, 0,23},{185,115,24, 0},{186,127,23, 1},{128,187, 1,23}, // 180-183
  170.  {120,188, 0,24},{189,115,25, 0},{190,127,24, 1},{128,191, 1,24}, // 184-187
  171.  {120,192, 0,25},{193,115,26, 0},{194,127,25, 1},{128,195, 1,25}, // 188-191
  172.  {120,196, 0,26},{197,115,27, 0},{198,127,26, 1},{128,199, 1,26}, // 192-195
  173.  {120,200, 0,27},{201,115,28, 0},{202,127,27, 1},{128,203, 1,27}, // 196-199
  174.  {120,204, 0,28},{205,115,29, 0},{206,127,28, 1},{128,207, 1,28}, // 200-203
  175.  {120,208, 0,29},{209,125,30, 0},{210,127,29, 1},{128,211, 1,29}, // 204-207
  176.  {130,212, 0,30},{213,125,31, 0},{214,137,30, 1},{138,215, 1,30}, // 208-211
  177.  {130,216, 0,31},{217,125,32, 0},{218,137,31, 1},{138,219, 1,31}, // 212-215
  178.  {130,220, 0,32},{221,125,33, 0},{222,137,32, 1},{138,223, 1,32}, // 216-219
  179.  {130,224, 0,33},{225,125,34, 0},{226,137,33, 1},{138,227, 1,33}, // 220-223
  180.  {130,228, 0,34},{229,125,35, 0},{230,137,34, 1},{138,231, 1,34}, // 224-227
  181.  {130,232, 0,35},{233,125,36, 0},{234,137,35, 1},{138,235, 1,35}, // 228-231
  182.  {130,236, 0,36},{237,125,37, 0},{238,137,36, 1},{138,239, 1,36}, // 232-235
  183.  {130,240, 0,37},{241,125,38, 0},{242,137,37, 1},{138,243, 1,37}, // 236-239
  184.  {130,244, 0,38},{245,135,39, 0},{246,137,38, 1},{138,247, 1,38}, // 240-243
  185.  {140,248, 0,39},{249,135,40, 0},{250, 69,39, 1},{ 80,251, 1,39}, // 244-247
  186.  {140,252, 0,40},{249,135,41, 0},{250, 69,40, 1},{ 80,251, 1,40}, // 248-251
  187.  {140,252, 0,41}};  // 252, 253-255 are reserved
  188.  
  189. #define nex(state,sel) State_table[state][sel]
  190.  
  191. //////////////////////////// StateMap //////////////////////////
  192.  
  193. // A StateMap maps a context to a probability.  Methods:
  194. //
  195. // Statemap sm(n) creates a StateMap with n contexts using 4*n bytes memory.
  196. // sm.p(cx, limit) converts state cx (0..n-1) to a probability (0..4095)
  197. //     that the next updated bit y=1.
  198. //     limit (1..1023, default 255) is the maximum count for computing a
  199. //     prediction.  Larger values are better for stationary sources.
  200. // sm.update(y) updates the model with actual bit y (0..1).
  201.  
  202. class StateMap {
  203. protected:
  204.  const int N;  // Number of contexts
  205.  int cxt;      // Context of last prediction
  206.  U32 *t;       // cxt -> prediction in high 22 bits, count in low 10 bits
  207.  static int dt[1024];  // i -> 16K/(i+3)
  208. public:
  209.  StateMap(int n=256);
  210.  
  211.  // update bit y (0..1)
  212.  void update(int y, int limit=255) {
  213.    assert(cxt>=0 && cxt<N);
  214.    int n=t[cxt]&1023, p=t[cxt]>>10;  // count, prediction
  215.    if (n<limit) ++t[cxt];
  216.    else t[cxt]=t[cxt]&0xfffffc00|limit;
  217.    t[cxt]+=(((y<<22)-p)>>3)*dt[n]&0xfffffc00;
  218.  }
  219.  
  220.  // predict next bit in context cx
  221.  int p(int cx) {
  222.    assert(cx>=0 && cx<N);
  223.    return t[cxt=cx]>>20;
  224.  }
  225. };
  226.  
  227. int StateMap::dt[1024]={0};
  228.  
  229. StateMap::StateMap(int n): N(n), cxt(0) {
  230.  alloc(t, N);
  231.  for (int i=0; i<N; ++i)
  232.    t[i]=1<<31;
  233.  if (dt[0]==0)
  234.    for (int i=0; i<1024; ++i)
  235.      dt[i]=16384/(i+i+3);
  236. }
  237.  
  238. //////////////////////////// Mix, APM /////////////////////////
  239.  
  240. // Mix combines 2 predictions and a context to produce a new prediction.
  241. // Methods:
  242. // Mix m(n) -- creates allowing with n contexts.
  243. // m.pp(p1, p2, cx) -- inputs 2 stretched predictions and a context cx
  244. //   (0..n-1) and returns a stretched prediction.  Stretched predictions
  245. //   are fixed point numbers with an 8 bit fraction, normally -2047..2047
  246. //   representing -8..8, such that 1/(1+exp(-p) is the probability that
  247. //   the next update will be 1.
  248. // m.update(y) updates the model after a prediction with bit y (0..1).
  249.  
  250. class Mix {
  251. protected:
  252.  const int N;  // n
  253.  int* wt;  // weights, scaled 24 bits
  254.  int x1, x2;    // inputs, scaled 8 bits (-2047 to 2047)
  255.  int cxt;  // last context (0..n-1)
  256.  int pr;   // last output
  257. public:
  258.  Mix(int n=512);
  259.  int pp(int p1, int p2, int cx) {
  260.    assert(cx>=0 && cx<N);
  261.    cxt=cx*2;
  262.    return pr=(x1=p1)*(wt[cxt]>>16)+(x2=p2)*(wt[cxt+1]>>16)+128>>8;
  263.  }
  264.  void update(int y) {
  265.    assert(y==0 || y==1);
  266.    int err=((y<<12)-squash(pr));
  267.    if ((wt[cxt]&3)<3)
  268.      err*=4-(++wt[cxt]&3);
  269.    err=err+8>>4;
  270.    wt[cxt]+=x1*err&-4;
  271.    wt[cxt+1]+=x2*err;
  272.  }
  273. };
  274.  
  275. Mix::Mix(int n): N(n), x1(0), x2(0), cxt(0), pr(0) {
  276.  alloc(wt, n*2);
  277.  for (int i=0; i<N*2; ++i)
  278.    wt[i]=1<<23;
  279. }
  280.  
  281. // An APM is a Mix optimized for a constant in place of p1, used to
  282. // refine a stretched prediction given a context cx.
  283. // Normally p1 is in the range (0..4095) and p2 is doubled.
  284.  
  285. class APM: public Mix {
  286. public:
  287.  APM(int n);
  288. };
  289.  
  290. APM::APM(int n): Mix(n) {
  291.  for (int i=0; i<n; ++i)
  292.    wt[2*i]=0;
  293. }
  294.  
  295. //////////////////////////// HashTable /////////////////////////
  296.  
  297. // A HashTable maps a 32-bit index to an array of B bytes.
  298. // The first byte is a checksum using the upper 8 bits of the
  299. // index.  The second byte is a priority (0 = empty) for hash
  300. // replacement.  The index need not be a hash.
  301.  
  302. // HashTable<B> h(n) - create using n bytes  n and B must be
  303. //     powers of 2 with n >= B*4, and B >= 2.
  304. // h[i] returns array [1..B-1] of bytes indexed by i, creating and
  305. //     replacing another element if needed.  Element 0 is the
  306. //     checksum and should not be modified.
  307.  
  308. template <int B>
  309. class HashTable {
  310.  U8* t;  // table: 1 element = B bytes: checksum priority data data
  311.  const U32 N;  // size in bytes
  312. public:
  313.  HashTable(int n);
  314.  ~HashTable();
  315.  U8* operator[](U32 i);
  316. };
  317.  
  318. template <int B>
  319. HashTable<B>::HashTable(int n): t(0), N(n) {
  320.  assert(B>=2 && (B&B-1)==0);
  321.  assert(N>=B*4 && (N&N-1)==0);
  322.  alloc(t, N+B*4+64);
  323.  t+=64-int(((long)t)&63);  // align on cache line boundary
  324. }
  325.  
  326. template <int B>
  327. inline U8* HashTable<B>::operator[](U32 i) {
  328.  i*=123456791;
  329.  i=i<<16|i>>16;
  330.  i*=234567891;
  331.  int chk=i>>24;
  332.  i=i*B&N-B;
  333.  if (t[i]==chk) return t+i;
  334.  if (t[i^B]==chk) return t+(i^B);
  335.  if (t[i^B*2]==chk) return t+(i^B*2);
  336.  if (t[i+1]>t[i+1^B] || t[i+1]>t[i+1^B*2]) i^=B;
  337.  if (t[i+1]>t[i+1^B^B*2]) i^=B^B*2;
  338.  memset(t+i, 0, B);
  339.  t[i]=chk;
  340.  return t+i;
  341. }
  342.  
  343. template <int B>
  344. HashTable<B>::~HashTable() {
  345.  int c=0, c0=0;
  346.  for (U32 i=0; i<N; ++i) {
  347.    if (t[i]) {
  348.      ++c;
  349.      if (i%B==0) ++c0;
  350.    }
  351.  }
  352.  printf("HashTable<%d> %1.4f%% full, %1.4f%% utilized of %d KiB\n",
  353.    B, 100.0*c0*B/N, 100.0*c/N, N>>10);
  354. }
  355.  
  356. ////////////////////////// LZP /////////////////////////
  357.  
  358. U32 MEM=1<<29;  // Global memory limit, 1 << 22+(memory option)
  359.  
  360. // LZP predicts the next byte and maintains context.  Methods:
  361. // c() returns the predicted byte for the next update, or -1 if none.
  362. // p() returns the 12 bit probability (0..4095) that c() is next.
  363. // update(ch) updates the model with actual byte ch (0..255).
  364. // c(i) returns the i'th prior byte of context, i > 0.
  365. // c4() returns the order 4 context, shifted into the LSB.
  366. // c8() returns a hash of the order 8 context, shifted 4 bits into LSB.
  367. // word0, word1 are hashes of the current and previous word (a-z).
  368.  
  369. class LZP {
  370. private:
  371.  const int N, H; // buf, t sizes
  372.  enum {MINLEN=12};  // minimum match length
  373.  U8* buf;     // Rotating buffer of size N
  374.  U32* t;      // hash table of pointers in high 24 bits, state in low 8 bits
  375.  int match;   // start of match
  376.  int len;     // length of match
  377.  int pos;     // position of next ch to write to buf
  378.  U32 h;       // context hash
  379.  U32 h1;      // hash of last 8 byte updates, shifting 4 bits to MSB
  380.  U32 h2;      // last 4 updates, shifting 8 bits to MSB
  381.  StateMap sm1; // len+offset -> p
  382.  APM a1, a2, a3;   // p, context -> p
  383.  int literals, matches;  // statistics
  384. public:
  385.  U32 word0, word1;  // hashes of last 2 words (case insensitive a-z)
  386.  LZP();
  387.  ~LZP();
  388.  int c();     // predicted char
  389.  int c(int i);// context
  390.  int c4() {return h2;}  // order 4 context, c(1) in LSB
  391.  int c8() {return h1;}  // hashed order 8 context
  392.  int p();     // probability that next char is c() * 4096
  393.  void update(int ch);  // update model with actual char ch
  394. };
  395.  
  396. // Initialize
  397. LZP::LZP(): N(MEM/8), H(MEM/32),
  398.    match(-1), len(0), pos(0), h(0), h1(0), h2(0),
  399.    sm1(0x200), a1(0x10000), a2(0x40000), a3(0x100000),
  400.    literals(0), matches(0), word0(0), word1(0) {
  401.  assert(MEM>0);
  402.  assert(H>0);
  403.  alloc(buf, N);
  404.  alloc(t, H);
  405. }
  406.  
  407. // Print statistics
  408. LZP::~LZP() {
  409.  int c=0;
  410.  for (int i=0; i<H; ++i)
  411.    c+=(t[i]!=0);
  412.  printf("LZP hash table %1.4f%% full of %d KiB\n"
  413.    "LZP buffer %1.4f%% full of %d KiB\n",
  414.    100.0*c/H, H>>8, pos<N?100.0*pos/N:100.0, N>>10);
  415.  printf("LZP %d literals, %d matches (%1.4f%% matched)\n",
  416.    literals, matches,
  417.    literals+matches>0?100.0*matches/(literals+matches):0.0);
  418. }
  419.  
  420. // Predicted next byte, or -1 for no prediction
  421. inline int LZP::c() {
  422.  return len>=MINLEN ? buf[match&N-1] : -1;
  423. }
  424.  
  425. // Return i'th byte of context (i > 0)
  426. inline int LZP::c(int i) {
  427.  assert(i>0);
  428.  return buf[pos-i&N-1];
  429. }
  430.  
  431. // Return prediction that c() will be the next byte (0..4095)
  432. int LZP::p() {
  433.  if (len<MINLEN) return 0;
  434.  int cxt=len;
  435.  if (len>28) cxt=28+(len>=32)+(len>=64)+(len>=128);
  436.  int pc=c();
  437.  int pr=sm1.p(cxt);
  438.  pr=stretch(pr);
  439.  pr=a1.pp(2048, pr*2, h2*256+pc&0xffff)*3+pr>>2;
  440.  pr=a2.pp(2048, pr*2, h1*(11<<6)+pc&0x3ffff)*3+pr>>2;
  441.  pr=a3.pp(2048, pr*2, h1*(7<<4)+pc&0xfffff)*3+pr>>2;
  442.  pr=squash(pr);
  443.  return pr;
  444. }
  445.  
  446. // Update model with predicted byte ch (0..255)
  447. void LZP::update(int ch) {
  448.  int y=c()==ch;     // 1 if prediction of ch was right, else 0
  449.  h1=h1*(3<<4)+ch+1; // update context hashes
  450.  h2=h2<<8|ch;
  451.  h=h*(5<<2)+ch+1&H-1;
  452.  if (len>=MINLEN) {
  453.    sm1.update(y);
  454.    a1.update(y);
  455.    a2.update(y);
  456.    a3.update(y);
  457.  }
  458.  if (isalpha(ch))
  459.    word0=word0*(29<<2)+tolower(ch);
  460.  else if (word0)
  461.    word1=word0, word0=0;
  462.  buf[pos&N-1]=ch;   // update buf
  463.  ++pos;
  464.  if (y) {  // extend match
  465.    ++len;
  466.    ++match;
  467.    ++matches;
  468.  }
  469.  else {  // find new match, try order 6 context first
  470.    ++literals;
  471.    y=0;
  472.    len=1;
  473.    match=t[h];
  474.    if (!((match^pos)&N-1)) --match;
  475.    while (len<=128 && buf[match-len&N-1]==buf[pos-len&N-1]) ++len;
  476.    --len;
  477.  }
  478.  t[h]=pos;
  479. }
  480.  
  481. LZP* lzp=0;
  482.  
  483. //////////////////////////// Predictor /////////////////////////
  484.  
  485. // A Predictor estimates the probability that the next bit of
  486. // uncompressed data is 1.  Methods:
  487. // Predictor() creates.
  488. // p() returns P(1) as a 12 bit number (0-4095).
  489. // update(y) trains the predictor with the actual bit (0 or 1).
  490.  
  491. class Predictor {
  492.  enum {N=11}; // number of contexts
  493.  int c0;      // last 0-7 bits with leading 1, 0 before LZP flag
  494.  int nibble;  // last 0-3 bits with leading 1 (1..15)
  495.  int bcount;  // number of bits in c0 (0..7)
  496.  HashTable<16> t;  // context -> state
  497.  StateMap sm[N];   // state -> prediction
  498.  U8* cp[N];   // i -> state array of bit histories for i'th context
  499.  U8* sp[N];   // i -> pointer to bit history for i'th context
  500.  Mix m[N-1];  // combines 2 predictions given a context
  501.  APM a1, a2, a3;  // adjusts a prediction given a context
  502.  U8* t2;      // order 1 contexts -> state
  503.  
  504. public:
  505.  Predictor();
  506.  int p();
  507.  void update(int y);
  508. };
  509.  
  510. // Initialize
  511. Predictor::Predictor():
  512.    c0(0), nibble(1), bcount(0), t(MEM/2),
  513.    a1(0x10000), a2(0x10000), a3(0x10000) {
  514.  alloc(t2, 0x40000);
  515.  for (int i=0; i<N; ++i)
  516.    sp[i]=cp[i]=t2;
  517. }
  518.  
  519. // Update model
  520. void Predictor::update(int y) {
  521.  assert(y==0 || y==1);
  522.  assert(bcount>=0 && bcount<8);
  523.  assert(c0>=0 && c0<256);
  524.  assert(nibble>=1 && nibble<=15);
  525.  if (c0==0)
  526.    c0=1-y;
  527.  else {
  528.    *sp[0]=nex(*sp[0], y);
  529.    sm[0].update(y);
  530.    for (int i=1; i<N; ++i) {
  531.      *sp[i]=nex(*sp[i], y);
  532.      sm[i].update(y);
  533.      m[i-1].update(y);
  534.    }
  535.    c0+=c0+y;
  536.    if (++bcount==8) bcount=c0=0;
  537.    if ((nibble+=nibble+y)>=16) nibble=1;
  538.    a1.update(y);
  539.    a2.update(y);
  540.    a3.update(y);
  541.  }
  542. }
  543.  
  544. // Predict next bit
  545. int Predictor::p() {
  546.  assert(lzp);
  547.  if (c0==0)
  548.    return lzp->p();
  549.  else {
  550.  
  551.    // Set context pointers
  552.    int pc=lzp->c();  // mispredicted byte
  553.    int r=pc+256>>8-bcount==c0;  // c0 consistent with mispredicted byte?
  554.    U32 c4=lzp->c4();  // last 4 whole context bytes, shifted into LSB
  555.    U32 c8=(lzp->c8()<<4)-1;  // hash of last 7 bytes with 4 trailing 1 bits
  556.    if ((bcount&3)==0) {  // nibble boundary?  Update context pointers
  557.      pc&=-r;
  558.      U32 c4p=c4<<8;
  559.      if (bcount==0) {  // byte boundary?  Update order-1 context pointers
  560.        cp[0]=t2+(c4>>16&0xff00);
  561.        cp[1]=t2+(c4>>8 &0xff00)+0x10000;
  562.        cp[2]=t2+(c4    &0xff00)+0x20000;
  563.        cp[3]=t2+(c4<<8 &0xff00)+0x30000;
  564.      }
  565.      cp[4]=t[(c4p&0xffff00)-c0];
  566.      cp[5]=t[(c4p&0xffffff00)*3+c0];
  567.      cp[6]=t[c4*7+c0];
  568.      cp[7]=t[(c8*5&0xfffffc)+c0];
  569.      cp[8]=t[(c8*11&0xffffff0)+c0+pc*13];
  570.      cp[9]=t[lzp->word0*5+c0+pc*17];
  571.      cp[10]=t[lzp->word1*7+lzp->word0*11+c0+pc*37];
  572.    }
  573.  
  574.    // Mix predictions
  575.    r<<=8;
  576.    sp[0]=&cp[0][c0];
  577.    int pr=stretch(sm[0].p(*sp[0]));
  578.    for (int i=1; i<N; ++i) {
  579.      sp[i]=&cp[i][i<4?c0:nibble];
  580.      int st=*sp[i];
  581.      pr=m[i-1].pp(pr, stretch(sm[i].p(st)), st+r)*3+pr>>2;
  582.    }
  583.    pr=a1.pp(512, pr*2, c0+pc*256&0xffff)*3+pr>>2;  // Adjust prediction
  584.    pr=a2.pp(512, pr*2, c4<<8&0xff00|c0)*3+pr>>2;
  585.    pr=a3.pp(512, pr*2, c4*3+c0&0xffff)*3+pr>>2;
  586.    return squash(pr);
  587.  }
  588. }
  589.  
  590. Predictor* predictor=0;
  591.  
  592. /////////////////////////// get4, put4 //////////////////////////
  593.  
  594. // Read/write a 4 byte big-endian number
  595. int get4(FILE* in) {
  596.  int r=getc(in);
  597.  r=r*256+getc(in);
  598.  r=r*256+getc(in);
  599.  r=r*256+getc(in);
  600.  return r;
  601. }
  602.  
  603. void put4(U32 c, FILE* out) {
  604.  fprintf(out, "%c%c%c%c", c>>24, c>>16, c>>8, c);
  605. }
  606.  
  607. //////////////////////////// Encoder ////////////////////////////
  608.  
  609. // An Encoder arithmetic codes in blocks of size BUFSIZE.  Methods:
  610. // Encoder(COMPRESS, f) creates encoder for compression to archive f, which
  611. //     must be open past any header for writing in binary mode.
  612. // Encoder(DECOMPRESS, f) creates encoder for decompression from archive f,
  613. //     which must be open past any header for reading in binary mode.
  614. // code(i) in COMPRESS mode compresses bit i (0 or 1) to file f.
  615. // code() in DECOMPRESS mode returns the next decompressed bit from file f.
  616. // count() should be called after each byte is compressed.
  617. // flush() should be called after compression is done.  It is also called
  618. //   automatically when a block is written.
  619.  
  620. typedef enum {COMPRESS, DECOMPRESS} Mode;
  621. class Encoder {
  622. private:
  623.  const Mode mode;       // Compress or decompress?
  624.  FILE* archive;         // Compressed data file
  625.  U32 x1, x2;            // Range, initially [0, 1), scaled by 2^32
  626.  U32 x;                 // Decompress mode: last 4 input bytes of archive
  627.  enum {BUFSIZE=0x20000};
  628.  static unsigned char* buf; // Compression output buffer, size BUFSIZE
  629.  int usize, csize;      // Buffered uncompressed and compressed sizes
  630.  double usum, csum;     // Total of usize, csize
  631.  
  632. public:
  633.  Encoder(Mode m, FILE* f);
  634.  void flush();  // call this when compression is finished
  635.  
  636.  // Compress bit y or return decompressed bit
  637.  int code(int y=0) {
  638.    assert(predictor);
  639.    int p=predictor->p();
  640.    assert(p>=0 && p<4096);
  641.    p+=p<2048;
  642.    U32 xmid=x1 + (x2-x1>>12)*p + ((x2-x1&0xfff)*p>>12);
  643.    assert(xmid>=x1 && xmid<x2);
  644.    if (mode==DECOMPRESS) y=x<=xmid;
  645.    y ? (x2=xmid) : (x1=xmid+1);
  646.    predictor->update(y);
  647.    while (((x1^x2)&0xff000000)==0) {  // pass equal leading bytes of range
  648.      if (mode==COMPRESS) buf[csize++]=x2>>24;
  649.      x1<<=8;
  650.      x2=(x2<<8)+255;
  651.      if (mode==DECOMPRESS) x=(x<<8)+getc(archive);
  652.    }
  653.    return y;
  654.  }
  655.  
  656.  // Count one byte
  657.  void count() {
  658.    assert(mode==COMPRESS);
  659.    ++usize;
  660.    if (csize>BUFSIZE-256)
  661.      flush();
  662.  }
  663. };
  664. unsigned char* Encoder::buf=0;
  665.  
  666. // Create in mode m (COMPRESS or DECOMPRESS) with f opened as the archive.
  667. Encoder::Encoder(Mode m, FILE* f):
  668.    mode(m), archive(f), x1(0), x2(0xffffffff), x(0),
  669.    usize(0), csize(0), usum(0), csum(0) {
  670.  if (mode==DECOMPRESS) {  // x = first 4 bytes of archive
  671.    for (int i=0; i<4; ++i)
  672.      x=(x<<8)+(getc(archive)&255);
  673.    csize=4;
  674.  }
  675.  else if (!buf)
  676.    alloc(buf, BUFSIZE);
  677. }
  678.  
  679. // Write a compressed block and reinitialize the encoder.  The format is:
  680. //   uncompressed size (usize, 4 byte, MSB first)
  681. //   compressed size (csize, 4 bytes, MSB first)
  682. //   compressed data (csize bytes)
  683. void Encoder::flush() {
  684.  if (mode==COMPRESS) {
  685.    buf[csize++]=x1>>24;
  686.    buf[csize++]=255;
  687.    buf[csize++]=255;
  688.    buf[csize++]=255;
  689.    putc(0, archive);
  690.    putc('c', archive);
  691.    put4(usize, archive);
  692.    put4(csize, archive);
  693.    fwrite(buf, 1, csize, archive);
  694.    usum+=usize;
  695.    csum+=csize+10;
  696.    printf("%15.0f -> %15.0f"
  697.      "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
  698.      usum, csum);
  699.    x1=x=usize=csize=0;
  700.    x2=0xffffffff;
  701.  }
  702. }
  703.  
  704. /////////////////////////// paq9a ////////////////////////////////
  705.  
  706. // Compress or decompress from in to out, depending on whether mode
  707. // is COMPRESS or DECOMPRESS.  A byte c is encoded as a 1 bit if it
  708. // is predicted by LZP, otherwise a 0 followed by 8 bits from MSB to LSB.
  709. void paq9a(FILE* in, FILE* out, Mode mode) {
  710.  if (!lzp && !predictor) {
  711.    lzp=new LZP;
  712.    predictor=new Predictor;
  713.    printf("%8d KiB\b\b\b\b\b\b\b\b\b\b\b\b", allocated>>10);
  714.  }
  715.  if (mode==COMPRESS) {
  716.    Encoder e(COMPRESS, out);
  717.    int c;
  718.    while ((c=getc(in))!=EOF) {
  719.      int cp=lzp->c();
  720.      if (c==cp)
  721.        e.code(1);
  722.      else
  723.        for (int i=8; i>=0; --i)
  724.          e.code(c>>i&1);
  725.      e.count();
  726.      lzp->update(c);
  727.    }
  728.    e.flush();
  729.  }
  730.  else {  // DECOMPRESS
  731.    int usize=get4(in);
  732.    get4(in);  // csize
  733.    Encoder e(DECOMPRESS, in);
  734.    while (usize--) {
  735.      int c=lzp->c();
  736.      if (e.code()==0) {
  737.        c=1;
  738.        while (c<256) c+=c+e.code();
  739.        c&=255;
  740.      }
  741.      if (out) putc(c, out);
  742.      lzp->update(c);
  743.    }
  744.  }
  745. }
  746.  
  747.  
  748. ///////////////////////////// store ///////////////////////////
  749.  
  750. // Store a file in blocks as: {'\0' mode usize csize contents}...
  751. void store(FILE* in, FILE* out) {
  752.  assert(in);
  753.  assert(out);
  754.  
  755.  // Store in blocks
  756.  const int BLOCKSIZE=0x100000;
  757.  static char* buf=0;
  758.  if (!buf) alloc(buf, BLOCKSIZE);
  759.  bool first=true;
  760.  while (true) {
  761.    int n=fread(buf, 1, BLOCKSIZE, in);
  762.    if (!first && n<=0) break;
  763.    fprintf(out, "%c%c", 0, 's');
  764.    put4(n, out);  // usize
  765.    put4(n, out);  // csize
  766.    fwrite(buf, 1, n, out);
  767.    first=false;
  768.  }
  769.  
  770.  // Close file
  771.  fclose(in);
  772. }
  773.  
  774. // Write usize == csize bytes of an uncompressed block from in to out
  775. void unstore(FILE* in, FILE* out) {
  776.  assert(in);
  777.  int usize=get4(in);
  778.  int csize=get4(in);
  779.  if (usize!=csize)
  780.    printf("Bad archive format: usize=%d csize=%d\n", usize, csize);
  781.  static char* buf=0;
  782.  const int BUFSIZE=0x1000;
  783.  if (!buf) alloc(buf, BUFSIZE);
  784.  while (csize>0) {
  785.    usize=csize;
  786.    if (usize>BUFSIZE) usize=BUFSIZE;
  787.    if (int(fread(buf, 1, usize, in))!=usize)
  788.      printf("Unexpected end of archive\n"), exit(1);
  789.    if (out) fwrite(buf, 1, usize, out);
  790.    csize-=usize;
  791.  }
  792. }
  793.  
  794. //////////////////////// Archiving functions ////////////////////////
  795.  
  796. const int MAXNAMELEN=1023;  // max filename length
  797.  
  798. // Return true if the first 4 bytes of in are a valid archive
  799. bool check_archive(FILE* in) {
  800.  return getc(in)=='p' && getc(in)=='Q' && getc(in)=='9' && getc(in)==1;
  801. }
  802.  
  803. // Open archive and check for valid archive header, exit if bad.
  804. // Set MEM to memory option '1' through '9'
  805. FILE* open_archive(const char* filename) {
  806.  FILE* in=fopen(filename, "rb");
  807.  if (!in)
  808.    printf("Cannot find archive %s\n", filename), exit(1);
  809.  if (!check_archive(in) || (MEM=getc(in))<'1' || MEM>'9') {
  810.    fclose(in);
  811.    printf("%s: Not a paq9a archive\n", filename);
  812.    exit(1);
  813.  }
  814.  return in;
  815. }
  816.  
  817. // Compress filename to out.  option is 'c' to compress or 's' to store.
  818. void compress(const char* filename, FILE* out, int option) {
  819.  
  820.  // Open input file
  821.  FILE* in=fopen(filename, "rb");
  822.  if (!in) {
  823.    printf("File not found: %s\n", filename);
  824.    return;
  825.  }
  826.  fprintf(out, "%s", filename);
  827.  printf("%-40s ", filename);
  828.  
  829.  // Compress depending on option
  830.  if (option=='s')
  831.    store(in, out);
  832.  else if (option=='c')
  833.    paq9a(in, out, COMPRESS);
  834.  printf("\n");
  835. }
  836.  
  837. // List archive contents
  838. void list(const char* archive) {
  839.  double usum=0, csum=0;  // uncompressed and compressed size per file
  840.  double utotal=0, ctotal=4;  // total size in archive
  841.  static char filename[MAXNAMELEN+1];
  842.  int mode=0;
  843.  
  844.  FILE* in=open_archive(archive);
  845.  printf("\npaq9a -%c\n", MEM);
  846.  while (true) {
  847.  
  848.    // Get filename, mode
  849.    int c=getc(in);
  850.    if (c==EOF) break;
  851.    if (c) {   // start of new file?  Print previous file
  852.      if (mode)
  853.        printf("%10.0f -> %10.0f %c %s\n", usum, csum, mode, filename);
  854.      int len=0;
  855.      filename[len++]=c;
  856.      while ((c=getc(in))!=EOF && c)
  857.        if (len<MAXNAMELEN) filename[len++]=c;
  858.      filename[len]=0;
  859.      utotal+=usum;
  860.      ctotal+=csum;
  861.      usum=0;
  862.      csum=len;
  863.    }
  864.  
  865.    // Get uncompressed size
  866.    mode=getc(in);
  867.    int usize=get4(in);
  868.    usum+=usize;
  869.  
  870.    // Get compressed size
  871.    int csize=get4(in);
  872.    csum+=csize+10;
  873.  
  874.    if (usize<0 || csize<0 || mode!='c' && mode!='s')
  875.      printf("Archive corrupted usize=%d csize=%d mode=%d at %ld\n",
  876.        usize, csize, mode, ftell(in)), exit(1);
  877.  
  878.    // Skip csize bytes
  879.    const int BUFSIZE=0x1000;
  880.    char buf[BUFSIZE];
  881.    while (csize>BUFSIZE)
  882.      csize-=fread(buf, 1, BUFSIZE, in);
  883.    fread(buf, 1, csize, in);
  884.  }
  885.  printf("%10.0f -> %10.0f %c %s\n", usum, csum, mode, filename);
  886.  utotal+=usum;
  887.  ctotal+=csum;
  888.  printf("%10.0f -> %10.0f total\n", utotal, ctotal);
  889.  fclose(in);
  890. }
  891.  
  892. // Extract files given command line arguments
  893. // Input format is: [filename {'\0' mode usize csize contents}...]...
  894. void extract(int argc, char** argv) {
  895.  assert(argc>2);
  896.  assert(argv[1][0]=='x');
  897.  static char filename[MAXNAMELEN+1];  // filename from archive
  898.  
  899.  // Open archive
  900.  FILE* in=open_archive(argv[2]);
  901.  MEM=1<<22+MEM-'0';
  902.  
  903.  // Extract files
  904.  argc-=3;
  905.  argv+=3;
  906.  FILE* out=0;
  907.  while (true) {  // for each block
  908.  
  909.    // Get filename
  910.    int c;
  911.    for (int i=0;; ++i) {
  912.      c=getc(in);
  913.      if (c==EOF) break;
  914.      if (i<MAXNAMELEN) filename[i]=c;
  915.      if (!c) break;
  916.    }
  917.    if (c==EOF) break;
  918.  
  919.    // Open output file
  920.    if (filename[0]) {  // new file?
  921.      const char* fn=filename;
  922.      if (argc>0) fn=argv[0], --argc, ++argv;
  923.      if (out) fclose(out);
  924.      out=fopen(fn, "rb");
  925.      if (out) {
  926.        printf("\nCannot overwrite file, skipping: %s ", fn);
  927.        fclose(out);
  928.        out=0;
  929.      }
  930.      else {
  931.        out=fopen(fn, "wb");
  932.        if (!out) printf("\nCannot create file: %s ", fn);
  933.      }
  934.      if (out) {
  935.        if (fn==filename) printf("\n%s ", filename);
  936.        else printf("\n%s -> %s ", filename, fn);
  937.      }
  938.    }
  939.  
  940.    // Extract block
  941.    int mode=getc(in);
  942.    if (mode=='s')
  943.      unstore(in, out);
  944.    else if (mode=='c')
  945.      paq9a(in, out, DECOMPRESS);
  946.    else
  947.      printf("\nUnsupported compression mode %c %d at %ld\n",
  948.        mode, mode, ftell(in)), exit(1);
  949.  }
  950.  printf("\n");
  951.  if (out) fclose(out);
  952. }
  953.  
  954. // Command line is: paq9a {a|x|l} archive [[-option] files...]...
  955. int main(int argc, char** argv) {
  956.  clock_t start=clock();
  957.  
  958.  // Check command line arguments
  959.  if (argc<3 || argv[1][1] || (argv[1][0]!='a' && argv[1][0]!='x'
  960.      && argv[1][0]!='l') || (argv[1][0]=='a' && argc<4) || argv[2][0]=='-')
  961.  {
  962.    printf("paq9a archiver (C) 2007, Matt Mahoney\n"
  963.      "Free software under GPL, http://www.gnu.org/copyleft/gpl.html\n"
  964.      "\n"
  965.      "To create archive: paq9a a archive [-1..-9] [[-s|-c] files...]...\n"
  966.      "  -1..-9 = use 18 to 1585 MiB memory (default -7 = 408 MiB)\n"
  967.      "  -s = store, -c = compress (default)\n"
  968.      "To extract files:  paq9a x archive [files...]\n"
  969.      "To list contents:  paq9a l archive\n");
  970.    exit(1);
  971.  }
  972.  
  973.  // Create archive
  974.  if (argv[1][0]=='a') {
  975.    int option = 'c';  // -c or -s
  976.    FILE* out=fopen(argv[2], "rb");
  977.    if (out) printf("Cannot overwrite archive %s\n", argv[2]), exit(1);
  978.    out=fopen(argv[2], "wb");
  979.    if (!out) printf("Cannot create archive %s\n", argv[2]), exit(1);
  980.    fprintf(out, "pQ9%c", 1);
  981.    int i=3;
  982.    if (argc>3 && argv[3][0]=='-' && argv[3][1]>='1' && argv[3][1]<='9'
  983.        && argv[3][2]==0) {
  984.      putc(argv[3][1], out);
  985.      MEM=1<<22+argv[3][1]-'0';
  986.      ++i;
  987.    }
  988.    else
  989.      putc('7', out);
  990.    for (; i<argc; ++i) {
  991.      if (argv[i][0]=='-' && (argv[i][1]=='c' || argv[i][1]=='s')
  992.          && argv[i][2]==0)
  993.        option=argv[i][1];
  994.      else
  995.        compress(argv[i], out, option);
  996.    }
  997.    printf("-> %ld in %1.2f sec\n", ftell(out),
  998.      double(clock()-start)/CLOCKS_PER_SEC);
  999.  }
  1000.  
  1001.  // List archive contents
  1002.  else if (argv[1][0]=='l')
  1003.    list(argv[2]);
  1004.  
  1005.  // Extract from archive
  1006.  else if (argv[1][0]=='x') {
  1007.    extract(argc, argv);
  1008.    printf("%1.2f sec\n", double(clock()-start)/CLOCKS_PER_SEC);
  1009.  }
  1010.  
  1011.  // Report statistics
  1012.  delete predictor;
  1013.  delete lzp;
  1014.  printf("Used %d KiB memory\n", allocated>>10);
  1015.  return 0;
  1016. }
  1017.  


« Última modificación: 25 Febrero 2015, 23:12 pm por sabeeee » En línea

"Vengándose, uno iguala a su enemigo; perdonando, uno se muestra superior a él."
Francis Bacon
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
tmpgenc cual es el mejor compresor de video?
Multimedia
genexxx 1 4,004 Último mensaje 25 Abril 2005, 01:17 am
por Songoku
alguien sabe como puedo capturar la pantalla, mas rapido o mejor??? « 1 2 3 4 »
Programación Visual Basic
Belial & Grimoire 32 17,047 Último mensaje 6 Septiembre 2007, 06:01 am
por cobein
[Source]Compresor de ejecutables
Programación Visual Basic
LeandroA 1 2,243 Último mensaje 19 Marzo 2010, 21:05 pm
por EddyW
2 portatiles... ¿cual es mejor para el counter-strike source?
Hardware
NIGHTBIRD 5 4,207 Último mensaje 1 Marzo 2012, 00:50 am
por NIGHTBIRD
Lenguaje más rápido o mejor?
Programación General
andrecid 2 2,485 Último mensaje 19 Julio 2015, 22:23 pm
por ivancea96
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines