-
Notifications
You must be signed in to change notification settings - Fork 4
/
u128-discard-fixed-bits.c
127 lines (105 loc) · 3.45 KB
/
u128-discard-fixed-bits.c
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
/* This file is part of the Theseus distribution.
* Copyright 2020 Joshua E. Hill <[email protected]>
*
* Licensed under the 3-clause BSD license. For details, see the LICENSE file.
*
* Author(s)
* Joshua E. Hill, UL VS LLC.
* Joshua E. Hill, KeyPair Consulting, Inc. <[email protected]>
*/
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <sysexits.h>
#include "binio.h"
#include "binutil.h"
#include "globals-inst.h"
#include "precision.h"
noreturn static void useageExit(void) {
fprintf(stderr, "Usage:\n");
fprintf(stderr, "discard-fixed-bits-u128 inputfile outputgroup\n");
fprintf(stderr, "inputfile is assumed to be a stream of uint128_t\n");
fprintf(stderr, "outputgroup sent to stdout are uint32_tegers, with all fixed bits removed and the non-fixed bits moved to the LSB of the output.\n");
exit(EX_USAGE);
}
int main(int argc, char *argv[]) {
FILE *infp;
size_t datalen;
uint32_t *data = NULL;
uint32_t *dataPartition[4];
size_t i, j;
uint32_t bitmask[4];
uint32_t maxval, minval;
uint32_t bits;
double doubleBits;
int outputGroup;
assert(PRECISION(UINT_MAX) >= 32);
assert(PRECISION(SIZE_MAX) > 32);
if (argc != 3) {
useageExit();
}
outputGroup = atoi(argv[2]);
if ((infp = fopen(argv[1], "rb")) == NULL) {
perror("Can't open file");
exit(EX_NOINPUT);
}
datalen = readuint32file(infp, &data);
assert(data != NULL);
assert(datalen > 0);
assert((datalen % 4) == 0);
dataPartition[0] = calloc(datalen / 4, sizeof(uint32_t));
dataPartition[1] = calloc(datalen / 4, sizeof(uint32_t));
dataPartition[2] = calloc(datalen / 4, sizeof(uint32_t));
dataPartition[3] = calloc(datalen / 4, sizeof(uint32_t));
if ((dataPartition[0] == NULL) || (dataPartition[1] == NULL) || (dataPartition[2] == NULL) || (dataPartition[3] == NULL)) {
perror("Can't allocate partitions");
exit(EX_OSERR);
}
for (j = 0; j < datalen; j++) {
(dataPartition[j & 0x3])[j >> 2] = data[j];
}
fprintf(stderr, "Read in %zu uint32_ts\n", datalen);
if (fclose(infp) != 0) {
perror("Can't close intput file");
exit(EX_OSERR);
}
for (j = 0; j < 4; j++) {
maxval = 0;
minval = UINT_MAX;
for (i = 0; i < datalen / 4; i++) {
if ((dataPartition[j])[i] > maxval) {
maxval = (dataPartition[j])[i];
}
if ((dataPartition[j])[i] < minval) {
minval = (dataPartition[j])[i];
}
}
doubleBits = ceil(log2((double)maxval + 1.0));
assert(doubleBits >= 0.0);
bits = (uint32_t)doubleBits;
bitmask[j] = getActiveBits(dataPartition[j], datalen / 4);
fprintf(stderr, "Symbols in the range [%u, %u] (%u bit: bitmask 0x%08X)\n", minval, maxval, bits, bitmask[j]);
for (i = 0; i < datalen / 4; i++) {
(dataPartition[j])[i] = extractbits((dataPartition[j])[i], bitmask[j]);
}
}
fprintf(stderr, "%d bits total\n", __builtin_popcount(bitmask[0]) + __builtin_popcount(bitmask[1]) + __builtin_popcount(bitmask[2]) + __builtin_popcount(bitmask[3]));
fprintf(stderr, "Outputting group %d\n", outputGroup);
for (i = 0; i < datalen / 4; i++) {
if (fwrite(&((dataPartition[outputGroup])[i]), sizeof(uint32_t), 1, stdout) != 1) {
perror("Can't write output to stdout");
exit(EX_OSERR);
}
}
free(data);
free(dataPartition[0]);
free(dataPartition[1]);
free(dataPartition[2]);
free(dataPartition[3]);
return EX_OK;
}