File: shuffle_tables.c

package info (click to toggle)
libstreamvbyte 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 576 kB
  • sloc: ansic: 5,697; makefile: 69
file content (190 lines) | stat: -rw-r--r-- 5,220 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#define extract(c,i) (3 & (c >> 2*i))

typedef uint8_t (*code_len_function)(int c);

static uint8_t code_to_length(int c) {
  /* 0,1,2,3 codes-> 1,2,3,4 bytes */
  return c + 1;
}

static uint8_t code_to_length_0124(int c) {
  switch (c) {
  case 0: // 0 bytes
    return 0;
  case 1: // 1 byte
    return 1;
  case 2: // 2 bytes
    return 2;
  default: // 4 bytes
    return 4;
  }
}

//  Initializes the lengths tables. Meant to be called before
//  decoder_permutation/encoder_permutation functions.
static void lengths_init(uint8_t *lengths, code_len_function code_len) {
  for(int code = 0; code < 256; code++) {
    lengths[code] = 0;
    for(int i = 0; i < 4; i++ ) {
      int c = extract(code, i);
      lengths[code] += code_len(c);
    }
  }
}

// produces the decoder permutation tables
// as well as the "length" tables. The length table
// is the same for encoding and decoding.
// table should point at 256*16 bytes
// length should point at 256 bytes
static void decoder_permutation(uint8_t *table) {
  uint8_t *p = table;
  for(int code = 0; code < 256; code++) {
    int byte = 0;
    for(int i = 0; i < 4; i++ ) {
      int c = extract(code, i);
      int j;
      for( j = 0; j <= c; j++ )
        *p++ = byte++;
      for( ; j < 4; j++ )
        *p++ = -1;
    }
  }
}

// produces the encoder permutation tables
// table should point at 256*16 bytes
// length should point at 256 bytes initialized with init_lengths
static void encoder_permutation(uint8_t *table, uint8_t *lengths) {
  uint8_t *p = table;
  for(int code = 0; code < 256; code++) {
    for(int i = 0; i < 4; i++ ) {
      int c = extract(code, i);
      int j;
      for( j = 0; j <= c; j++ )
        *p++ = 4*i + j;
    }
    for( int i = lengths[code]; i < 16; i++ )
      *p++ = -1;
  }
}

// produces the decoder permutation tables
// table should point at 256*16 bytes
static void decoder_permutation_0124(uint8_t *table) {
  uint8_t *p = table;
  for(int code = 0; code < 256; code++) {
    int byte = 0;
    for(int i = 0; i < 4; i++ ) {
      int c = extract(code, i);
      if (c < 3) {
        // Here c stands for a number of bytes to copy, i.e. 0,1,2
        int j;
        for( j = 0; j < c; j++ )
          *p++ = byte++;
        for( ; j < 4; j++ )
          *p++ = -1;
      } else {
        // Otherwise always copy all 4 bytes
        for(int j = 0; j < 4; j++ )
          *p++ = byte++;
      }
    }
  }
}

// produces the encoder permutation tables
// table should point at 256*16 bytes
// length should point at 256 bytes initialized
// with lengths_init
static void encoder_permutation_0124(uint8_t *table, uint8_t *lengths) {
  uint8_t *p = table;
  for(int code = 0; code < 256; code++) {
    for(int i = 0; i < 4; i++ ) {
      int c = extract(code, i);
      if (c < 3) {
        for( int j = 1; j <= c; j++ )
          *p++ = 4*i + j - 1;
      } else {
        for( int j = 0; j <= c; j++ )
          *p++ = 4*i + j;
      }
    }
    for( int i = lengths[code]; i < 16; i++ )
      *p++ = -1;
  }
}

// to be used after calling either  decoder_permutation or encoder_permutation
// table should point at 256*16 bytes
static void print_permutation(uint8_t *table) {
  for(int code = 0; code < 256; code++) {
    int x;
    printf(" {");
    for(int i = 0; i < 15; i++)
      printf(" %2d,", x = (int8_t) table[code*16 + i]);
    printf( " %2d", x = (int8_t) table[code*16 + 15]);
    printf(" },    // %d%d%d%d\n",
           extract(code,0),
           extract(code,1),
           extract(code,2),
           extract(code,3));
  }
}

// to be used after calling either  decoder_permutation or encoder_permutation
// length should point at 256 bytes
static void print_lengths(uint8_t *length) {
  printf("{");
  printf("\n");
  for(int code = 0; code < 256; ) {
    for(int k = 0; k < 16 ; k++) {
      printf(" %2d,", length[code]);
      code++;
    }
    printf("\n");
  }
  printf(" }");
}

int main(int argc, char **argv) {
  uint8_t *encoder_table = (uint8_t *) malloc( sizeof(uint8_t[256][16]));
  uint8_t *decoder_table = (uint8_t *) malloc( sizeof(uint8_t[256][16]));
  uint8_t lengths[256];

  if (argc == 2 && 0 == strcmp(argv[1], "0124")) {
    printf("// using 0,1,2,4 bytes per value\n");
    lengths_init(lengths, code_to_length_0124);
    encoder_permutation_0124(encoder_table, lengths);
    decoder_permutation_0124(decoder_table);
  } else if (argc == 2 && 0 == strcmp(argv[1], "1234")) {
    printf("// using 1,2,3,4 bytes per value\n");
    lengths_init(lengths, code_to_length);
    encoder_permutation(encoder_table, lengths);
    decoder_permutation(decoder_table);
  } else {
    fprintf(stderr, "Usage: shuffle_tables <0124|1234> > src/streamvbyte_shuffle_tables.h\n");
    exit(EXIT_FAILURE);
  }

  printf("static uint8_t lengthTable[256] =");
  print_lengths(lengths);
  printf(";\n\n");

  printf("// decoding:\n");
  printf("static uint8_t shuffleTable[256][16] = {\n");
  print_permutation(decoder_table);
  printf("};\n\n");

  printf("// encoding:\n");
  printf("static uint8_t encodingShuffleTable[256][16] = {\n");
  print_permutation(encoder_table);
  printf("};\n");
  return 0;

}