File: bit_array_generate.c

package info (click to toggle)
libbitarray 2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 348 kB
  • sloc: ansic: 4,401; makefile: 117; cpp: 19; sh: 11
file content (151 lines) | stat: -rw-r--r-- 2,988 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
/*
 dev/bit_array_generate.c
 project: bit array C library
 url: https://github.com/noporpoise/BitArray/
 author: Isaac Turner <turner.isaac@gmail.com>
 license: Public Domain, no warranty
 date: Dec 2013
*/


// 64 bit words
// Array length can be zero
// Unused top bits must be zero

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> // memset
#include <stdint.h>

uint8_t reverse(uint8_t b)
{
  uint8_t r = 0;
  int i;

  for(i = 0; i < 8; i++)
  {
    r <<= 1;
    r |= b & 0x1;
    b >>= 1;
  }

  return r;
}

// Print table of bytes -> byte reverse
void generate_reverse()
{
  int i;
  printf("static const word_t reverse_table[256] = \n{\n ");
  for(i = 0; i < 256; i++)
  {
    if(i % 8 == 0 && i > 0)
      printf("\n ");

    printf(" 0x%02X%c", reverse(i), i == 255 ? '\n' : ',');
  }
  printf("};\n\n");
}

uint16_t morton(uint8_t b)
{
  uint16_t r = 0;
  int i;
  for(i = 0; i < 8; i++)
  {
    r |= (b & 0x1) << (2*i);
    b >>= 1;
  }
  return r;
}

// a is either 0 or 1, and is how much to shift by
void generate_morton(char a)
{
  int i;
  printf("static const word_t morton_table%c[256] = \n{\n ", a ? '1' : '0');
  for(i = 0; i < 256; i++)
  {
    if(i % 8 == 0 && i > 0)
      printf("\n ");

    uint16_t m = morton(i);

    if(a)
      m <<= 1;

    printf(" 0x%04X%c", m, i == 255 ? '\n' : ',');
  }
  printf("};\n\n");
}

unsigned int next_permutation(unsigned int v) 
{
  unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1
  // Next set to 1 the most significant bit to change, 
  // set to 0 the least significant ones, and add the necessary 1 bits.
  //return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
  return (t+1) | (((~t & (t+1)) - 1) >> (__builtin_ctz(v) + 1));
}

long factorial(int k)
{
  long r = k;
  for(k--; k > 1; k--)
  {
    r *= k;
  }
  return r;
}

void generate_shuffle()
{
  int i;

  printf("static const uint8_t shuffle_permutations[9] = {1");

  for(i = 1; i < 8; i++)
  {
    // nCk = n! / ((n-k)!k!)
    long combinations = factorial(8) / (factorial(8-i)*factorial(i));
    printf(", %li", combinations);
  }

  printf(", 1};\n");

  printf("static const uint8_t shuffle[9][70] = {\n");

  for(i = 0; i <= 8; i++)
  {
    printf(" // %i bits set\n", i);
    unsigned char init = i == 0 ? 0 : (0x1 << i) - 1;

    printf(" {0x%02X", (int)init);

    unsigned int c = next_permutation(init);
    int num;

    for(num = 1; num < 70; c = next_permutation(c), num++)
    {
      printf(num % 10 == 0 ? ",\n  " : ", ");
      printf("0x%02X", c <= 255 ? (int)c : 0);
    }

    printf(i < 8 ? "},\n" : "}\n};\n\n");
  }
}

int main()
{
  printf("// byte reverse look up table\n");
  generate_reverse();
  printf("// Morton table for interleaving bytes\n");
  generate_morton(0);
  printf("// Morton table for interleaving bytes, shifted left 1 bit\n");
  generate_morton(1);
  printf("// Tables for shuffling\n");
  generate_shuffle();
  return 1;
}