-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTools.C
More file actions
365 lines (337 loc) · 13.8 KB
/
Tools.C
File metadata and controls
365 lines (337 loc) · 13.8 KB
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#include <cstdint>
#include "Tools.h"
#include <cstdlib>
#include <string>
/**
* builds a 64-bit long out of an array of 8 bytes
*
* for example, suppose bytes[0] == 0x12
* and bytes[1] == 0x34
* and bytes[2] == 0x56
* and bytes[3] == 0x78
* and bytes[4] == 0x9a
* and bytes[5] == 0xbc
* and bytes[6] == 0xde
* and bytes[7] == 0xf0
* then buildLong(bytes) returns 0xf0debc9a78563412
*
* @param array of 8 bytes
* @return uint64_t where the low order byte is bytes[0] and
* the high order byte is bytes[7]
*/
uint64_t Tools::buildLong(uint8_t bytes[LONGSIZE]) {
unsigned long output = 0x0000000000000000;
for (int i = 7; i > -1; i--) {
output |= bytes[i];
if (i != 0) { output = output << 8; }
}
return output;
}
/**
* accepts as input an uint64_t and returns the designated byte
* within the uint64_t; returns 0 if the indicated byte number
* is out of range
*
* for example, getByte(0x1122334455667788, 7) returns 0x11
* getByte(0x1122334455667788, 1) returns 0x77
* getByte(0x1122334455667788, 8) returns 0
*
* @param uint64_t source that is the source data
* @param int32_t byteNum that indicates the byte to return (0 through 7)
* @return 0 if byteNum is out of range
* byte 0, 1, .., or 7 of source if byteNum is within range
*
* RESTRICTIONS: You cannot use an if statement, the ternary operator, switch
* statement or any other conditional statements.
* This means you need to come up with some clever method to get the
* code to return 0 if bytenum is out of range and
* the selected byte otherwise.
*/
uint64_t Tools::getByte(uint64_t source, int32_t byteNum) {
uint32_t byteCheck = byteNum & 0x7;
uint8_t check = (!(byteNum - byteCheck)) * 0xff;
unsigned long output = 0x00000000000000ff;
output = output << (byteNum * 8);
output = output & source;
output = output >> (byteNum * 8);
return output & check;
}
/**
* accepts as input an uint64_t and returns the bits low through
* high of the uint64_t. bit 0 is the low order bit and bit 63
* is the high order bit. returns 0 if the low or high bit numbers
* are out of range
*
* for example, getBits(0x8877665544332211, 0, 7) returns 0x11
* getBits(0x8877665544332211, 4, 11) returns 0x21
* getBits(0x8877665544332211, 0, 63) returns 0x8877665544332211
*
* @param uint64_t source that holds the bits to be grabbed and
* returned
* @param int32_t low that is the bit number of the lowest numbered
* bit to be returned
* @param int32_t high that is the bit number of the highest numbered
* bit to be returned
* @return an uint64_t that holds a subset of the source bits
* that is returned in the low order bits; 0 if low or high
* is out of range
*
*
* RESTRICTIONS: You can use an if statement to determine whether
* the low and high values are valid. The remaining statements
* need to be simple assignment statements. (No loops, switch,
* ternary operator , or other conditional statements....)
* The purpose of this restriction is to push you to write
* "clean" code.
*/
uint64_t Tools::getBits(uint64_t source, int32_t low, int32_t high) {
if (low < 0 || low > 63) return 0;
if (high < 0 || high > 63) return 0;
if (high < low) return 0;
int32_t size = high - low;
long mask = 0x8000000000000000;
mask = mask >> size;
uint64_t mask2 = (unsigned long) mask;
mask2 = mask2 >> (63 - high);
int64_t output = (source & mask2) >> low;
return output;
}
/**
* sets the bits of source in the range specified by the low and high
* parameters to 1 and returns that value. returns source if the low or high
* bit numbers are out of range
*
* for example, setBits(0x1122334455667788, 0, 7) returns 0x11223344556677ff
* setBits(0x1122334455667788, 8, 0xf) returns 0x112233445566ff88
* setBits(0x1122334455667788, 8, 64) returns 0x1122334455667788
* note: 64 is out of range
*
* @param uint64_t source
* @param int32_t low that is the bit number of the lowest numbered
* bit to be set to 1
* @param int32_t high that is the bit number of the highest numbered
* bit to be set to 1
* @return an uint64_t that holds the modified source
*
* RESTRICTIONS: You can use an if statement to determine whether
* the low and high values are valid. The remaining statements
* need to be simple assignment statements. (No loops, switch,
* ternary operator, or other conditional statements ....)
* You can use other functions that you have written.
* The purpose of this restriction is to push you to write
* "clean" code.
*/
uint64_t Tools::setBits(uint64_t source, int32_t low, int32_t high) {
if (low < 0 || low > 63) return source;
if (high < 0 || high > 63) return source;
if (high < low) return source;
int32_t size = high - low;
int64_t maskTemp = 0x8000000000000000;
maskTemp = maskTemp >> size;
uint64_t mask = (unsigned long) maskTemp;
mask = mask >> (63 - high);
int64_t output = source | mask;
return output;
}
/**
* sets the bits of source in the range low to high to 0 (clears them) and
* returns that value. returns source if the low or high
* bit numbers are out of range
*
* for example, clearBits(0x1122334455667788, 0, 7) returns 0x1122334455667700
* clearBits(0x1122334455667788, 8, 15) returns 0x1122334455660088
*
* @param uint64_t source
* @param int32_t low that is the bit number of the lowest numbered
* bit to be set to 0
* @param int32_t high that is the bit number of the highest numbered
* bit to be set to 0
* @return an uint64_t that holds the modified source
*
* RESTRICTIONS: You can use an if statement to determine whether
* the low and high values are valid. The remaining statements
* need to be simple assignment statements. (No loops, switch,
* ternary operator, or other conditional statements ....)
* You can use other functions that you have written.
* The purpose of this restriction is to push you to write
* "clean" code.
*/
uint64_t Tools::clearBits(uint64_t source, int32_t low, int32_t high) {
if (low < 0 || low > 63) return source;
if (high < 0 || high > 63) return source;
if (high < low) return source;
int32_t size = high - low;
long mask = 0x8000000000000000;
mask = mask >> size;
uint64_t mask2 = (unsigned long) mask;
mask2 = mask2 >> (63 - high);
mask2 = ~mask2;
int64_t output = source & mask2;
return output;
}
/**
* copies length bits from the source to a destination and returns the
* modified destination. If low bit number of the source or
* dest is out of range or the calculated source or dest high bit
* number is out of range, then the unmodified destination is returned.
*
* for example,
* copyBits(0x1122334455667788, 0x8877665544332211, 0, 0, 8)
* returns 0x8877665544332288
* copyBits(0x1122334455667788, 0x8877665544332211, 0, 8, 8)
* returns 0x8877665544338811
*
* @param uint64_t source
* @param uint64_t dest
* @param int32_t srclow that is the bit number of the lowest numbered
* bit of the source to be copied
* @param int32_t destlow that is the bit number of the lowest numbered
* bit of the destination to be modified
* @param int32_t length that is the number of bits to be copied
* @return uint64_t that is the modifed dest
*
* RESTRICTIONS: You can use an if statement to determine whether
* the low and high values are valid. The remaining statements
* need to be simple assignment statements. (No loops, switch,
* ternary operator, or other conditional statements ....)
* You can use other functions that you have written.
* The purpose of this restriction is to push you to write
* "clean" code.
*/
uint64_t Tools::copyBits(uint64_t source, uint64_t dest,
int32_t srclow, int32_t dstlow, int32_t length) {
/*
printf("\n\n");
printf("Source: %lx\n", source);
printf("Dest: %lx\n", dest);
printf("srclow: %d, dstlow: %d, len: %d\n", srclow, dstlow, length);
*/
if (srclow < 0 || srclow > 63) return dest;
if (dstlow < 0 || dstlow > 63) return dest;
if (srclow + length > 64) return dest;
if (dstlow + length > 64) return dest;
// Clear the dest at the correct bits
uint64_t clearDest = clearBits(dest, dstlow, dstlow + length - 1);
//printf("\tclearDest: %lx\n", clearDest);
// Create a mask
int64_t maskTemp = 0x8000000000000000;
maskTemp = maskTemp >> (length - 1);
uint64_t mask = (uint64_t) maskTemp;
// Move mask to correct spot on source
mask = mask >> (64 - length);
mask = mask << srclow;
//printf("\tmask: %lx\n", mask);
// Get bits from source
int64_t transferBits = mask & source;
transferBits = transferBits >> srclow;
// Move transferBits to proper spot on clearDest
transferBits = transferBits << dstlow;
//printf("\ttransferBits: %lx\n", transferBits);
// Produce output with an bitwise or
uint64_t output = clearDest | transferBits;
//printf("\toutput: %lx\n\n", output);
return output;
}
/**
* sets the bits of source identfied by the byte number to 1 and
* returns that value. if the byte number is out of range then source
* is returned unchanged.
*
* for example, setByte(0x1122334455667788, 0) returns 0x11223344556677ff
* setByte(0x1122334455667788, 1) returns 0x112233445566ff88
* setByte(0x1122334455667788, 8) returns 0x1122334455667788
*
* @param uint64_t source
* @param int32_t byteNum that indicates the number of the byte to be
* set to 0xff; the low order byte is byte number 0
* @return uint64_t that is source with byte byteNum set to 0xff
*
* RESTRICTIONS: You cannot use an if statement, the ternary operator, switch
* statement or any other conditional statements.
* This means you need to come up with some clever method to get the
* code to return unmodified source if bytenum is out of range and
* the modified source otherwise.
*
*/
uint64_t Tools::setByte(uint64_t source, int32_t byteNum) {
uint32_t byteCheck = byteNum & 0x7;
uint64_t check = (!(byteNum - byteCheck)) * 0xffffffffffffffff;
uint64_t mask = 0x00000000000000ff;
mask = mask << (byteNum * 8);
uint64_t output = source | mask;
return (output & check) | (source & ~check);
}
/**
* assumes source contains a 64 bit two's complement value and
* returns the sign (1 or 0)
*
* for example, sign(0xffffffffffffffff) returns 1
* sign(0x0000000000000000) returns 0
* sign(0x8000000000000000) returns 1
*
* @param uint64_t source
* @return 1 if source is negative when treated as a two's complement
* value and 0 otherwise
*
* RESTRICTIONS: You cannot use an if statement, ternary operator, switch statement
* or any other conditional statement.
*
*/
uint8_t Tools::sign(uint64_t source) {
return source >> 63;
}
/**
* assumes that op1 and op2 contain 64 bit two's complement values
* and returns true if an overflow would occur if they are summed
* and false otherwise
*
* for example, addOverflow(0x8000000000000000, 0x8000000000000000) returns 1
* addOverflow(0x7fffffffffffffff, 0x7fffffffffffffff) returns 1
* addOverflow(0x8000000000000000, 0x7fffffffffffffff) returns 0
*
* @param uint64_t op1 that is one of the operands of the addition
* @param uint64_t op2 that is the other operand of the addition
* @return true if op1 + op2 would result in an overflow assuming that op1
* and op2 contain 64-bit two's complement values
*
* RESTRICTIONS: You cannot use an if statement, ternary operator, switch statement
* or any other conditional statement. However, you can use other
* functions you have written and conditional expressions. For example,
* return op1 != op2;
* is allowed, but
* if (op1 != op2) return true;
* is not. The purpose of this restriction is to push you to write
* "clean" code.
*/
bool Tools::addOverflow(uint64_t op1, uint64_t op2) {
uint64_t result = op1 + op2;
bool same = !(sign(op1) ^ sign(op2));
bool output = same && (sign(result) != sign(op1));
return output;
}
/**
* assumes that op1 and op2 contain 64 bit two's complement values
* and returns true if an overflow would occur from op2 - op1
* and false otherwise
*
* for example, subOverflow(0x8000000000000000, 0x8000000000000000) returns 0
* subOverflow(0x7fffffffffffffff, 0x7fffffffffffffff) returns 0
* subOverflow(0x8000000000000000, 0x7fffffffffffffff) returns 1
*
* @param uint64_t op1 that is one of the operands of the subtraction
* @param uint64_t op2 that is the other operand of the subtraction
* @return true if op2 - op1 would result in an overflow assuming that op1
* and op2 contain 64-bit two's complement values
*
* RESTRICTIONS: You cannot use an if statement, ternary operator, switch statement
* or any other conditional statement. However, you can use other
* functions you have written and conditional expressions. For example,
* return op1 != op2;
* is allowed, but
* if (op1 != op2) return true;
* is not. The purpose of this restriction is to push you to write
* "clean" code.
*/
bool Tools::subOverflow(uint64_t op1, uint64_t op2) {
return addOverflow(~op2+1, op1);
}