authorgravatar for tgschultz@gmail.comtgschultz <tgschultz@gmail.com> 2019-05-04 16:19:26+00:00
committergravatar for tgschultz@gmail.comtgschultz <tgschultz@gmail.com> 2019-05-04 16:19:26+00:00
log14a00d3825df34a993d7579869aa0204400e9fde
tree789b782261be2b6b584055ad82a013144803caa1
parent8c28b5960559daef3ffc6b0777829ae3262ee8c7

zig fmt


1 files changed, 203 insertions(+), 263 deletions(-)

std/packed_int_array.zig+203-263
......@@ -3,148 +3,134 @@ const builtin = @import("builtin");
33const debug = std.debug;
44const testing = std.testing;
55
6pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type
7{
6pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
87 //The general technique employed here is to cast bytes in the array to a container
98 // integer (having bits % 8 == 0) large enough to contain the number of bits we want,
109 // then we can retrieve or store the new value with a relative minimum of masking
1110 // and shifting. In this worst case, this means that we'll need an integer that's
1211 // actually 1 byte larger than the minimum required to store the bits, because it
13 // is possible that the bits start at the end of the first byte, continue through
12 // is possible that the bits start at the end of the first byte, continue through
1413 // zero or more, then end in the beginning of the last. But, if we try to access
1514 // a value in the very last byte of memory with that integer size, that extra byte
1615 // will be out of bounds. Depending on the circumstances of the memory, that might
1716 // mean the OS fatally kills the program. Thus, we use a larger container (MaxIo)
1817 // most of the time, but a smaller container (MinIo) when touching the last byte
1918 // of the memory.
20
2119 const int_bits = comptime std.meta.bitCount(Int);
22
20
2321 //in the best case, this is the number of bytes we need to touch
2422 // to read or write a value, as bits
2523 const min_io_bits = ((int_bits + 7) / 8) * 8;
26
24
2725 //in the worst case, this is the number of bytes we need to touch
2826 // to read or write a value, as bits
29 const max_io_bits = switch(int_bits)
30 {
27 const max_io_bits = switch (int_bits) {
3128 0 => 0,
3229 1 => 8,
3330 2...9 => 16,
3431 10...65535 => ((int_bits / 8) + 2) * 8,
3532 else => unreachable,
3633 };
37
34
3835 //we bitcast the desired Int type to an unsigned version of itself
3936 // to avoid issues with shifting signed ints.
4037 const UnInt = @IntType(false, int_bits);
41
38
4239 //The maximum container int type
4340 const MinIo = @IntType(false, min_io_bits);
44
41
4542 //The minimum container int type
4643 const MaxIo = @IntType(false, max_io_bits);
47
48 return struct
49 {
50 pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int
51 {
52 if(int_bits == 0) return 0;
53
44
45 return struct {
46 pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int {
47 if (int_bits == 0) return 0;
48
5449 const bit_index = (index * int_bits) + bit_offset;
5550 const max_end_byte = (bit_index + max_io_bits) / 8;
56
51
5752 //Using the larger container size will potentially read out of bounds
58 if(max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
53 if (max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
5954 return getBits(bytes, MaxIo, bit_index);
6055 }
61
62 fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int
63 {
56
57 fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int {
6458 const container_bits = comptime std.meta.bitCount(Container);
6559 const Shift = std.math.Log2Int(Container);
66
60
6761 const start_byte = bit_index / 8;
6862 const head_keep_bits = bit_index - (start_byte * 8);
6963 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
70
64
7165 //read bytes as container
72 const value_ptr = @ptrCast(*const align(1) Container, &bytes[start_byte]);
66 const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
7367 var value = value_ptr.*;
74
75 if(endian != builtin.endian) value = @bswap(Container, value);
76
77 switch(endian)
78 {
79 .Big =>
80 {
68
69 if (endian != builtin.endian) value = @bswap(Container, value);
70
71 switch (endian) {
72 .Big => {
8173 value <<= @intCast(Shift, head_keep_bits);
8274 value >>= @intCast(Shift, head_keep_bits);
8375 value >>= @intCast(Shift, tail_keep_bits);
8476 },
85 .Little =>
86 {
77 .Little => {
8778 value <<= @intCast(Shift, tail_keep_bits);
8879 value >>= @intCast(Shift, tail_keep_bits);
8980 value >>= @intCast(Shift, head_keep_bits);
9081 },
9182 }
92
83
9384 return @bitCast(Int, @truncate(UnInt, value));
9485 }
95
96 pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void
97 {
98 if(int_bits == 0) return;
86
87 pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void {
88 if (int_bits == 0) return;
9989
10090 const bit_index = (index * int_bits) + bit_offset;
10191 const max_end_byte = (bit_index + max_io_bits) / 8;
102
92
10393 //Using the larger container size will potentially write out of bounds
104 if(max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
94 if (max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
10595 setBits(bytes, MaxIo, bit_index, int);
10696 }
107
108 fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void
109 {
97
98 fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void {
11099 const container_bits = comptime std.meta.bitCount(Container);
111100 const Shift = std.math.Log2Int(Container);
112
101
113102 const start_byte = bit_index / 8;
114103 const head_keep_bits = bit_index - (start_byte * 8);
115104 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
116 const keep_shift = switch(endian)
117 {
105 const keep_shift = switch (endian) {
118106 .Big => @intCast(Shift, tail_keep_bits),
119107 .Little => @intCast(Shift, head_keep_bits),
120108 };
121
109
122110 //position the bits where they need to be in the container
123111 const value = @intCast(Container, @bitCast(UnInt, int)) << keep_shift;
124
112
125113 //read existing bytes
126114 const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
127115 var target = target_ptr.*;
128
129 if(endian != builtin.endian) target = @bswap(Container, target);
130
116
117 if (endian != builtin.endian) target = @bswap(Container, target);
118
131119 //zero the bits we want to replace in the existing bytes
132120 const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
133121 const mask = ~inv_mask;
134122 target &= mask;
135
123
136124 //merge the new value
137125 target |= value;
138
139 if(endian != builtin.endian) target = @bswap(Container, target);
140
126
127 if (endian != builtin.endian) target = @bswap(Container, target);
128
141129 //save it back
142130 target_ptr.* = target;
143131 }
144
145 fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize)
146 PackedIntSliceEndian(Int, endian)
147 {
132
133 fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
148134 debug.assert(end >= start);
149135
150136 const length = end - start;
......@@ -152,28 +138,26 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type
152138 const start_byte = bit_index / 8;
153139 const end_byte = (bit_index + (length * int_bits) + 7) / 8;
154140 const new_bytes = bytes[start_byte..end_byte];
155
156 if(length == 0) return PackedIntSliceEndian(Int, endian).init(new_bytes[0..0], 0);
157
141
142 if (length == 0) return PackedIntSliceEndian(Int, endian).init(new_bytes[0..0], 0);
143
158144 var new_slice = PackedIntSliceEndian(Int, endian).init(new_bytes, length);
159145 new_slice.bit_offset = @intCast(u3, (bit_index - (start_byte * 8)));
160146 return new_slice;
161147 }
162
163 fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: builtin.Endian,
164 bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian)
165 {
148
149 fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: builtin.Endian, bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian) {
166150 const new_int_bits = comptime std.meta.bitCount(NewInt);
167151 const New = PackedIntSliceEndian(NewInt, new_endian);
168
152
169153 const total_bits = (old_len * int_bits);
170154 const new_int_count = total_bits / new_int_bits;
171
155
172156 debug.assert(total_bits == new_int_count * new_int_bits);
173
157
174158 var new = New.init(bytes, new_int_count);
175159 new.bit_offset = bit_offset;
176
160
177161 return new;
178162 }
179163 };
......@@ -182,187 +166,160 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type
182166///Creates a bit-packed array of integers of type Int. Bits
183167/// are packed using native endianess and without storing any meta
184168/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.
185pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type
186{
169pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {
187170 return PackedIntArrayEndian(Int, builtin.endian, int_count);
188171}
189172
190173///Creates a bit-packed array of integers of type Int. Bits
191174/// are packed using specified endianess and without storing any meta
192175/// data.
193pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian,
194 comptime int_count: usize) type
195{
176pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian, comptime int_count: usize) type {
196177 const int_bits = comptime std.meta.bitCount(Int);
197178 const total_bits = int_bits * int_count;
198179 const total_bytes = (total_bits + 7) / 8;
199
180
200181 const Io = PackedIntIo(Int, endian);
201
202 return struct
203 {
182
183 return struct {
204184 const Self = @This();
205
185
206186 bytes: [total_bytes]u8,
207
187
208188 ///Returns the number of elements in the packed array
209 pub fn len(self: Self) usize
210 {
189 pub fn len(self: Self) usize {
211190 return int_count;
212191 }
213
192
214193 ///Initialize a packed array using an unpacked array
215194 /// or, more likely, an array literal.
216 pub fn init(ints: [int_count]Int) Self
217 {
195 pub fn init(ints: [int_count]Int) Self {
218196 var self = Self(undefined);
219 for(ints) |int, i| self.set(i, int);
197 for (ints) |int, i| self.set(i, int);
220198 return self;
221199 }
222
200
223201 ///Return the Int stored at index
224 pub fn get(self: Self, index: usize) Int
225 {
202 pub fn get(self: Self, index: usize) Int {
226203 debug.assert(index < int_count);
227204 return Io.get(self.bytes, index, 0);
228205 }
229
206
230207 ///Copy int into the array at index
231 pub fn set(self: *Self, index: usize, int: Int) void
232 {
208 pub fn set(self: *Self, index: usize, int: Int) void {
233209 debug.assert(index < int_count);
234210 return Io.set(&self.bytes, index, 0, int);
235211 }
236
212
237213 ///Create a PackedIntSlice of the array from given start to given end
238 pub fn slice(self: *Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian)
239 {
214 pub fn slice(self: *Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
240215 debug.assert(start < int_count);
241216 debug.assert(end <= int_count);
242217 return Io.slice(&self.bytes, 0, start, end);
243218 }
244
219
245220 ///Create a PackedIntSlice of the array using NewInt as the bit width integer.
246221 /// NewInt's bit width must fit evenly within the array's Int's total bits.
247 pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt)
248 {
222 pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt) {
249223 return self.sliceCastEndian(NewInt, endian);
250224 }
251
225
252226 ///Create a PackedIntSlice of the array using NewInt as the bit width integer
253227 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
254228 /// the array's Int's total bits.
255 pub fn sliceCastEndian(self: *Self, comptime NewInt: type,
256 comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian)
257 {
229 pub fn sliceCastEndian(self: *Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
258230 return Io.sliceCast(&self.bytes, NewInt, new_endian, 0, int_count);
259231 }
260232 };
261233}
262234
263///Uses a slice as a bit-packed block of int_count integers of type Int.
235///Uses a slice as a bit-packed block of int_count integers of type Int.
264236/// Bits are packed using native endianess and without storing any meta
265237/// data.
266pub fn PackedIntSlice(comptime Int: type) type
267{
238pub fn PackedIntSlice(comptime Int: type) type {
268239 return PackedIntSliceEndian(Int, builtin.endian);
269240}
270241
271///Uses a slice as a bit-packed block of int_count integers of type Int.
242///Uses a slice as a bit-packed block of int_count integers of type Int.
272243/// Bits are packed using specified endianess and without storing any meta
273244/// data.
274pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) type
275{
245pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) type {
276246 const int_bits = comptime std.meta.bitCount(Int);
277247 const Io = PackedIntIo(Int, endian);
278
279 return struct
280 {
248
249 return struct {
281250 const Self = @This();
282
251
283252 bytes: []u8,
284253 int_count: usize,
285254 bit_offset: u3,
286
255
287256 ///Returns the number of elements in the packed slice
288 pub fn len(self: Self) usize
289 {
257 pub fn len(self: Self) usize {
290258 return self.int_count;
291259 }
292
260
293261 ///Calculates the number of bytes required to store a desired count
294262 /// of Ints
295 pub fn bytesRequired(int_count: usize) usize
296 {
263 pub fn bytesRequired(int_count: usize) usize {
297264 const total_bits = int_bits * int_count;
298265 const total_bytes = (total_bits + 7) / 8;
299266 return total_bytes;
300267 }
301
268
302269 ///Initialize a packed slice using the memory at bytes, with int_count
303270 /// elements. bytes must be large enough to accomodate the requested
304271 /// count.
305 pub fn init(bytes: []u8, int_count: usize) Self
306 {
272 pub fn init(bytes: []u8, int_count: usize) Self {
307273 debug.assert(bytes.len >= bytesRequired(int_count));
308
309 return Self
310 {
274
275 return Self{
311276 .bytes = bytes,
312277 .int_count = int_count,
313278 .bit_offset = 0,
314279 };
315280 }
316
281
317282 ///Return the Int stored at index
318 pub fn get(self: Self, index: usize) Int
319 {
283 pub fn get(self: Self, index: usize) Int {
320284 debug.assert(index < self.int_count);
321285 return Io.get(self.bytes, index, self.bit_offset);
322286 }
323
287
324288 ///Copy int into the array at index
325 pub fn set(self: *Self, index: usize, int: Int) void
326 {
289 pub fn set(self: *Self, index: usize, int: Int) void {
327290 debug.assert(index < self.int_count);
328291 return Io.set(self.bytes, index, self.bit_offset, int);
329292 }
330
293
331294 ///Create a PackedIntSlice of this slice from given start to given end
332 pub fn slice(self: Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian)
333 {
295 pub fn slice(self: Self, start: usize, end: usize) PackedIntSliceEndian(Int, endian) {
334296 debug.assert(start < self.int_count);
335297 debug.assert(end <= self.int_count);
336298 return Io.slice(self.bytes, self.bit_offset, start, end);
337299 }
338
300
339301 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer.
340302 /// NewInt's bit width must fit evenly within this slice's Int's total bits.
341 pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSliceEndian(NewInt, endian)
342 {
303 pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSliceEndian(NewInt, endian) {
343304 return self.sliceCastEndian(NewInt, endian);
344305 }
345
306
346307 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer
347308 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
348309 /// this slice's Int's total bits.
349 pub fn sliceCastEndian(self: Self, comptime NewInt: type,
350 comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian)
351 {
310 pub fn sliceCastEndian(self: Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {
352311 return Io.sliceCast(self.bytes, NewInt, new_endian, self.bit_offset, self.int_count);
353312 }
354313 };
355314}
356315
357test "PackedIntArray"
358{
316test "PackedIntArray" {
359317 @setEvalBranchQuota(10000);
360318 const max_bits = 256;
361319 const int_count = 19;
362
320
363321 comptime var bits = 0;
364 inline while(bits <= 256):(bits += 1)
365 {
322 inline while (bits <= 256) : (bits += 1) {
366323 //alternate unsigned and signed
367324 const even = bits % 2 == 0;
368325 const I = @IntType(even, bits);
......@@ -370,100 +327,90 @@ test "PackedIntArray"
370327 const PackedArray = PackedIntArray(I, int_count);
371328 const expected_bytes = ((bits * int_count) + 7) / 8;
372329 testing.expect(@sizeOf(PackedArray) == expected_bytes);
373
330
374331 var data = PackedArray(undefined);
375
332
376333 //write values, counting up
377334 var i = usize(0);
378335 var count = I(0);
379 while(i < data.len()):(i += 1)
380 {
336 while (i < data.len()) : (i += 1) {
381337 data.set(i, count);
382 if(bits > 0) count +%= 1;
338 if (bits > 0) count +%= 1;
383339 }
384
340
385341 //read and verify values
386342 i = 0;
387343 count = 0;
388 while(i < data.len()):(i += 1)
389 {
344 while (i < data.len()) : (i += 1) {
390345 const val = data.get(i);
391346 testing.expect(val == count);
392 if(bits > 0) count +%= 1;
347 if (bits > 0) count +%= 1;
393348 }
394349 }
395350}
396351
397test "PackedIntArray init"
398{
352test "PackedIntArray init" {
399353 const PackedArray = PackedIntArray(u3, 8);
400 var packed_array = PackedArray.init([]u3{0,1,2,3,4,5,6,7});
354 var packed_array = PackedArray.init([]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
401355 var i = usize(0);
402 while(i < packed_array.len()):(i += 1) testing.expect(packed_array.get(i) == i);
356 while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i);
403357}
404358
405test "PackedIntSlice"
406{
359test "PackedIntSlice" {
407360 @setEvalBranchQuota(10000);
408361 const max_bits = 256;
409362 const int_count = 19;
410363 const total_bits = max_bits * int_count;
411364 const total_bytes = (total_bits + 7) / 8;
412
365
413366 var buffer: [total_bytes]u8 = undefined;
414
367
415368 comptime var bits = 0;
416 inline while(bits <= 256):(bits += 1)
417 {
369 inline while (bits <= 256) : (bits += 1) {
418370 //alternate unsigned and signed
419371 const even = bits % 2 == 0;
420372 const I = @IntType(even, bits);
421373 const P = PackedIntSlice(I);
422
374
423375 var data = P.init(&buffer, int_count);
424
376
425377 //write values, counting up
426378 var i = usize(0);
427379 var count = I(0);
428 while(i < data.len()):(i += 1)
429 {
380 while (i < data.len()) : (i += 1) {
430381 data.set(i, count);
431 if(bits > 0) count +%= 1;
382 if (bits > 0) count +%= 1;
432383 }
433
384
434385 //read and verify values
435386 i = 0;
436387 count = 0;
437 while(i < data.len()):(i += 1)
438 {
388 while (i < data.len()) : (i += 1) {
439389 const val = data.get(i);
440390 testing.expect(val == count);
441 if(bits > 0) count +%= 1;
391 if (bits > 0) count +%= 1;
442392 }
443393 }
444394}
445395
446test "PackedIntSlice of PackedInt(Array/Slice)"
447{
396test "PackedIntSlice of PackedInt(Array/Slice)" {
448397 const max_bits = 16;
449398 const int_count = 19;
450
399
451400 comptime var bits = 0;
452 inline while(bits <= max_bits):(bits += 1)
453 {
401 inline while (bits <= max_bits) : (bits += 1) {
454402 const Int = @IntType(false, bits);
455
403
456404 const PackedArray = PackedIntArray(Int, int_count);
457405 var packed_array = PackedArray(undefined);
458
406
459407 const limit = (1 << bits);
460
408
461409 var i = usize(0);
462 while(i < packed_array.len()):(i += 1)
463 {
410 while (i < packed_array.len()) : (i += 1) {
464411 packed_array.set(i, @intCast(Int, i % limit));
465412 }
466
413
467414 //slice of array
468415 var packed_slice = packed_array.slice(2, 5);
469416 testing.expect(packed_slice.len() == 3);
......@@ -475,10 +422,10 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
475422 testing.expect(packed_slice.get(2) == 4 % limit);
476423 packed_slice.set(1, 7 % limit);
477424 testing.expect(packed_slice.get(1) == 7 % limit);
478
425
479426 //write through slice
480427 testing.expect(packed_array.get(3) == 7 % limit);
481
428
482429 //slice of a slice
483430 const packed_slice_two = packed_slice.slice(0, 3);
484431 testing.expect(packed_slice_two.len() == 3);
......@@ -487,7 +434,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
487434 testing.expect(packed_slice_two.bytes.len == ps2_expected_bytes);
488435 testing.expect(packed_slice_two.get(1) == 7 % limit);
489436 testing.expect(packed_slice_two.get(2) == 4 % limit);
490
437
491438 //size one case
492439 const packed_slice_three = packed_slice_two.slice(1, 2);
493440 testing.expect(packed_slice_three.len() == 1);
......@@ -495,12 +442,12 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
495442 const ps3_expected_bytes = (ps3_bit_count + 7) / 8;
496443 testing.expect(packed_slice_three.bytes.len == ps3_expected_bytes);
497444 testing.expect(packed_slice_three.get(0) == 7 % limit);
498
445
499446 //empty slice case
500447 const packed_slice_empty = packed_slice.slice(0, 0);
501448 testing.expect(packed_slice_empty.len() == 0);
502449 testing.expect(packed_slice_empty.bytes.len == 0);
503
450
504451 //slicing at byte boundaries
505452 const packed_slice_edge = packed_array.slice(8, 16);
506453 testing.expect(packed_slice_edge.len() == 8);
......@@ -509,135 +456,134 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
509456 testing.expect(packed_slice_edge.bytes.len == pse_expected_bytes);
510457 testing.expect(packed_slice_edge.bit_offset == 0);
511458 }
512
513459}
514460
515test "PackedIntSlice accumulating bit offsets"
516{
461test "PackedIntSlice accumulating bit offsets" {
517462 //bit_offset is u3, so standard debugging asserts should catch
518463 // anything
519464 {
520465 const PackedArray = PackedIntArray(u3, 16);
521466 var packed_array = PackedArray(undefined);
522
467
523468 var packed_slice = packed_array.slice(0, packed_array.len());
524469 var i = usize(0);
525 while(i < packed_array.len() - 1):(i += 1)
526 {
527
470 while (i < packed_array.len() - 1) : (i += 1) {
528471 packed_slice = packed_slice.slice(1, packed_slice.len());
529472 }
530473 }
531474 {
532475 const PackedArray = PackedIntArray(u11, 88);
533476 var packed_array = PackedArray(undefined);
534
477
535478 var packed_slice = packed_array.slice(0, packed_array.len());
536479 var i = usize(0);
537 while(i < packed_array.len() - 1):(i += 1)
538 {
480 while (i < packed_array.len() - 1) : (i += 1) {
539481 packed_slice = packed_slice.slice(1, packed_slice.len());
540482 }
541483 }
542
543484}
544485
545486//@NOTE: As I do not have a big endian system to test this on,
546487// big endian values were not tested
547test "PackedInt(Array/Slice) sliceCast"
548{
488test "PackedInt(Array/Slice) sliceCast" {
549489 const PackedArray = PackedIntArray(u1, 16);
550 var packed_array = PackedArray.init([]u1{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1});
490 var packed_array = PackedArray.init([]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
551491 const packed_slice_cast_2 = packed_array.sliceCast(u2);
552492 const packed_slice_cast_4 = packed_slice_cast_2.sliceCast(u4);
553493 var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9);
554494 const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3);
555
495
556496 var i = usize(0);
557 while(i < packed_slice_cast_2.len()):(i += 1)
558 {
559 const val = switch(builtin.endian)
560 {
497 while (i < packed_slice_cast_2.len()) : (i += 1) {
498 const val = switch (builtin.endian) {
561499 .Big => 0b01,
562500 .Little => 0b10,
563501 };
564502 testing.expect(packed_slice_cast_2.get(i) == val);
565503 }
566504 i = 0;
567 while(i < packed_slice_cast_4.len()):(i += 1)
568 {
569 const val = switch(builtin.endian)
570 {
505 while (i < packed_slice_cast_4.len()) : (i += 1) {
506 const val = switch (builtin.endian) {
571507 .Big => 0b0101,
572508 .Little => 0b1010,
573509 };
574510 testing.expect(packed_slice_cast_4.get(i) == val);
575511 }
576512 i = 0;
577 while(i < packed_slice_cast_9.len()):(i += 1)
578 {
513 while (i < packed_slice_cast_9.len()) : (i += 1) {
579514 const val = 0b010101010;
580515 testing.expect(packed_slice_cast_9.get(i) == val);
581516 packed_slice_cast_9.set(i, 0b111000111);
582517 }
583518 i = 0;
584 while(i < packed_slice_cast_3.len()):(i += 1)
585 {
586 const val = switch(builtin.endian)
587 {
588 .Big => if(i % 2 == 0) u3(0b111) else u3(0b000),
589 .Little => if(i % 2 == 0) u3(0b111) else u3(0b000),
519 while (i < packed_slice_cast_3.len()) : (i += 1) {
520 const val = switch (builtin.endian) {
521 .Big => if (i % 2 == 0) u3(0b111) else u3(0b000),
522 .Little => if (i % 2 == 0) u3(0b111) else u3(0b000),
590523 };
591524 testing.expect(packed_slice_cast_3.get(i) == val);
592525 }
593526}
594527
595test "PackedInt(Array/Slice)Endian"
596{
528test "PackedInt(Array/Slice)Endian" {
597529 {
598530 const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
599 var packed_array_be = PackedArrayBe.init([]u4{0,1,2,3,4,5,6,7,});
531 var packed_array_be = PackedArrayBe.init([]u4{
532 0,
533 1,
534 2,
535 3,
536 4,
537 5,
538 6,
539 7,
540 });
600541 testing.expect(packed_array_be.bytes[0] == 0b00000001);
601542 testing.expect(packed_array_be.bytes[1] == 0b00100011);
602
543
603544 var i = usize(0);
604 while(i < packed_array_be.len()):(i += 1)
605 {
545 while (i < packed_array_be.len()) : (i += 1) {
606546 testing.expect(packed_array_be.get(i) == i);
607547 }
608
548
609549 var packed_slice_le = packed_array_be.sliceCastEndian(u4, .Little);
610550 i = 0;
611 while(i < packed_slice_le.len()):(i += 1)
612 {
613 const val = if(i % 2 == 0) i + 1 else i - 1;
551 while (i < packed_slice_le.len()) : (i += 1) {
552 const val = if (i % 2 == 0) i + 1 else i - 1;
614553 testing.expect(packed_slice_le.get(i) == val);
615554 }
616
555
617556 var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u4, .Little);
618557 i = 0;
619 while(i < packed_slice_le_shift.len()):(i += 1)
620 {
621 const val = if(i % 2 == 0) i else i + 2;
558 while (i < packed_slice_le_shift.len()) : (i += 1) {
559 const val = if (i % 2 == 0) i else i + 2;
622560 testing.expect(packed_slice_le_shift.get(i) == val);
623561 }
624562 }
625
563
626564 {
627565 const PackedArrayBe = PackedIntArrayEndian(u11, .Big, 8);
628 var packed_array_be = PackedArrayBe.init([]u11{0,1,2,3,4,5,6,7,});
566 var packed_array_be = PackedArrayBe.init([]u11{
567 0,
568 1,
569 2,
570 3,
571 4,
572 5,
573 6,
574 7,
575 });
629576 testing.expect(packed_array_be.bytes[0] == 0b00000000);
630577 testing.expect(packed_array_be.bytes[1] == 0b00000000);
631578 testing.expect(packed_array_be.bytes[2] == 0b00000100);
632579 testing.expect(packed_array_be.bytes[3] == 0b00000001);
633580 testing.expect(packed_array_be.bytes[4] == 0b00000000);
634
581
635582 var i = usize(0);
636 while(i < packed_array_be.len()):(i += 1)
637 {
583 while (i < packed_array_be.len()) : (i += 1) {
638584 testing.expect(packed_array_be.get(i) == i);
639585 }
640
586
641587 var packed_slice_le = packed_array_be.sliceCastEndian(u11, .Little);
642588 testing.expect(packed_slice_le.get(0) == 0b00000000000);
643589 testing.expect(packed_slice_le.get(1) == 0b00010000000);
......@@ -647,8 +593,7 @@ test "PackedInt(Array/Slice)Endian"
647593 testing.expect(packed_slice_le.get(5) == 0b00000000010);
648594 testing.expect(packed_slice_le.get(6) == 0b10000010000);
649595 testing.expect(packed_slice_le.get(7) == 0b00000111001);
650
651
596
652597 var packed_slice_le_shift = packed_array_be.slice(1, 5).sliceCastEndian(u11, .Little);
653598 testing.expect(packed_slice_le_shift.get(0) == 0b00010000000);
654599 testing.expect(packed_slice_le_shift.get(1) == 0b00000000100);
......@@ -666,44 +611,39 @@ test "PackedInt(Array/Slice)Endian"
666611// and reading the last element. The assumption is that the page
667612// after this one is not mapped and will cause a segfault if we
668613// don't account for the bounds.
669test "PackedIntArray at end of available memory"
670{
671 switch(builtin.os)
672 {
614test "PackedIntArray at end of available memory" {
615 switch (builtin.os) {
673616 .linux, .macosx, .ios, .freebsd, .netbsd => {},
674617 else => return,
675618 }
676619 const PackedArray = PackedIntArray(u3, 8);
677
678 const Padded = struct
679 {
620
621 const Padded = struct {
680622 _: [std.os.page_size - @sizeOf(PackedArray)]u8,
681623 p: PackedArray,
682624 };
683
625
684626 var da = std.heap.DirectAllocator.init();
685627 const allocator = &da.allocator;
686
628
687629 var pad = try allocator.create(Padded);
688630 defer allocator.destroy(pad);
689631 pad.p.set(7, std.math.maxInt(u3));
690632}
691633
692test "PackedIntSlice at end of available memory"
693{
694 switch(builtin.os)
695 {
634test "PackedIntSlice at end of available memory" {
635 switch (builtin.os) {
696636 .linux, .macosx, .ios, .freebsd, .netbsd => {},
697637 else => return,
698638 }
699639 const PackedSlice = PackedIntSlice(u11);
700
640
701641 var da = std.heap.DirectAllocator.init();
702642 const allocator = &da.allocator;
703
643
704644 var page = try allocator.alloc(u8, std.os.page_size);
705645 defer allocator.free(page);
706
707 var p = PackedSlice.init(page[std.os.page_size - 2..], 1);
646
647 var p = PackedSlice.init(page[std.os.page_size - 2 ..], 1);
708648 p.set(0, std.math.maxInt(u11));
709}
\ No newline at end of file
649}