-
Notifications
You must be signed in to change notification settings - Fork 0
/
traceuint.h
225 lines (175 loc) · 5.11 KB
/
traceuint.h
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifndef TRACEBIT
#define TRACEBIT
#include <set>
#include <iostream>
class TraceBit;
#define ZERO TraceBit()
#define ONE TraceBit(0)
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#include "tracebit_mod2.h"
//#include "tracebit_opcount.h"
template<int N, typename T>
class TraceUint;
typedef TraceUint<8, unsigned char> Tuint8;
typedef TraceUint<16, unsigned short> Tuint16;
typedef TraceUint<32, unsigned int> Tuint32;
typedef TraceUint<64, unsigned long long> Tuint64;
/* Template that defines a 1 to 8 byte integer using tracing bits
* The type of tracing is defined by the include above
* N = the number of bits
* T = the underlying unit type
*/
template<int N, typename T>
class TraceUint {
public:
TraceBit bits[N];
TraceUint()
{
}
// Initialize from the underlying uint type
TraceUint(const T& value)
{
for(int n =0; n < N; n++)
{
if (((value >> n) & 1) == 1)
bits[n] = ONE;
else
bits[n] = ZERO;
}
}
// Returns the underlying uint value
// Only possible if this contains no variable references
T Value() const {
T res = 0;
for(int n=0; n < N; n++)
{
int v = bits[n].Value();
if (v == 1)
res |= (1 << n);
else if (v <0)
throw "Can't create value from expression";
}
return res;
}
// Casting
// We're doing this unchecked
operator Tuint8() const {
Tuint8 result;
for(int n=0; n < 8; n++)
result.bits[n] = bits[n];
return result;
}
operator Tuint16() const {
Tuint16 result;
for(int n=0; n < MIN(16,N); n++)
result.bits[n] = bits[n];
return result;
}
operator Tuint32() const {
Tuint32 result;
for(int n=0; n < MIN(32,N); n++)
result.bits[n] = bits[n];
return result;
}
operator Tuint64() const {
Tuint64 result;
for(int n=0; n < MIN(64,N); n++)
result.bits[n] = bits[n];
return result;
}
// replaces a bit with a variable
// variable should be 1-15 refered to as x1 to x15
void SetVariable(int bit, int variable)
{
bits[bit] = TraceBit(variable);
}
// define bitwise operators
TraceUint operator&(const TraceUint &other) const {
TraceUint result = TraceUint();
for(int n=0; n < N; n++)
result.bits[n] = this->bits[n] & other.bits[n];
return result;
}
TraceUint operator|(const TraceUint &other) const {
TraceUint result = TraceUint();
for(int n=0; n < N; n++)
result.bits[n] = this->bits[n] | other.bits[n];
return result;
}
TraceUint operator^(const TraceUint &other) const {
TraceUint result = TraceUint();
for(int n=0; n < N; n++)
result.bits[n] = this->bits[n] ^ other.bits[n];
return result;
}
TraceUint operator>>(const int shift) const {
TraceUint result = TraceUint();
for(int n=0; n < (N-shift); n++)
result.bits[n] = this->bits[n + shift];
return result;
}
TraceUint operator<<(const int shift) const {
TraceUint result = TraceUint();
for(int n=shift; n < N; n++)
result.bits[n] = this->bits[n - shift];
return result;
}
TraceUint operator~() const {
TraceUint result = TraceUint();
for(int n=0; n < N; n++)
{
result.bits[n] = ~this->bits[n];
}
return result;
}
TraceUint operator+(const TraceUint &other) const {
TraceUint result = TraceUint();
// we need to apply the binary adder
TraceBit carry = ZERO;
for(int n=0; n < N; n++)
{
result.bits[n] = (this->bits[n] ^ other.bits[n])
^ carry;
carry = (this->bits[n] & other.bits[n])
| (carry & (this->bits[n] ^ other.bits[n]));
}
return result;
}
};
// Stream implementation
// Creates a binary-string with the content,
// embedding formulas where needed
template<int N, typename T>
std::ostream& operator<<(std::ostream& os, const TraceUint<N, T>& obj)
{
for(int n=N-1; n >=0; n--)
{
os << obj.bits[n].to_str();
}
return os;
}
// helper function for direct packing
static void tracebit_pack(Tuint32 *target, const Tuint8 * source)
{
for(int n=0;n<8; n++)
target->bits[n] = source[3].bits[n];
for(int n=0;n<8; n++)
target->bits[n+8] = source[2].bits[n];
for(int n=0;n<8; n++)
target->bits[n+16] = source[1].bits[n];
for(int n=0;n<8; n++)
target->bits[n+24] = source[0].bits[n];
}
static void tracebit_unpack(Tuint8 *target, const Tuint32 source)
{
for(int n=0;n<8; n++)
target[3].bits[n] = source.bits[n];
for(int n=0;n<8; n++)
target[2].bits[n] = source.bits[n+8];
for(int n=0;n<8; n++)
target[1].bits[n] = source.bits[n+16];
for(int n=0;n<8; n++)
target[0].bits[n] = source.bits[n+24];
}
#endif // TRACEBIT
//#define TEST_TRACEBIT