bf: add a module implementing operations with bit arrays (#1049)
							parent
							
								
									26af513e1b
								
							
						
					
					
						commit
						c4fcfcec88
					
				|  | @ -0,0 +1,179 @@ | |||
| module bf | ||||
| 
 | ||||
| struct BitField { | ||||
| mut: | ||||
| 	size int | ||||
| 	//field *u32
 | ||||
| 	field []u32 | ||||
| } | ||||
| 
 | ||||
| /* helper functions */ | ||||
| const ( | ||||
| 	SLOT_SIZE = 32 | ||||
| ) | ||||
| 
 | ||||
| fn bitmask(bitnr int) u32 { | ||||
| 	return u32(1 << (bitnr % SLOT_SIZE)) | ||||
| } | ||||
| 
 | ||||
| fn bitslot(size int) int { | ||||
| 	return size / SLOT_SIZE | ||||
| } | ||||
| 
 | ||||
| fn bitget(instance BitField, bitnr int) int { | ||||
| 	return (instance.field[bitslot(bitnr)] >> u32(bitnr % SLOT_SIZE)) & 1 | ||||
| } | ||||
| 
 | ||||
| fn bitset(instance BitField, bitnr int) { | ||||
| 	instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] | bitmask(bitnr) | ||||
| } | ||||
| 
 | ||||
| fn bitclear(instance BitField, bitnr int) { | ||||
| 	instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] & ~bitmask(bitnr) | ||||
| } | ||||
| 
 | ||||
| fn bittoggle(instance BitField, bitnr int) { | ||||
| 	instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] ^ bitmask(bitnr) | ||||
| } | ||||
| /* | ||||
| #define BITTEST(a, b) ((a)->field[BITSLOT(b)] & BITMASK(b)) | ||||
| */ | ||||
| 
 | ||||
| fn min(input1 int, input2 int) int { | ||||
| 	if input1 < input2 { | ||||
| 		return input1 | ||||
| 	} | ||||
| 	else { | ||||
| 		return input2 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn bitnslots(length int) int { | ||||
| 	return (length - 1) / SLOT_SIZE + 1 | ||||
| }  | ||||
| 
 | ||||
| fn cleartail(instance BitField) { | ||||
| 	tail := instance.size % SLOT_SIZE | ||||
| 	if tail != 0 { | ||||
| 		/* create a mask for the tail */ | ||||
| 		mask := u32((1 << tail) - 1) | ||||
| 		/* clear the extra bits */ | ||||
| 		instance.field[bitnslots(instance.size) - 1] = instance.field[bitnslots(instance.size) - 1] & mask | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* public functions */ | ||||
| 
 | ||||
| pub fn new(size int) BitField { | ||||
| 	output := BitField{ | ||||
| 		size: size  | ||||
| 		//field: *u32(calloc(bitnslots(size) * SLOT_SIZE / 8))
 | ||||
| 		field: [u32(0); bitnslots(size)] | ||||
| 	} | ||||
| 	return output | ||||
| } | ||||
| /* | ||||
| pub fn del(instance *BitField) { | ||||
| 	free(instance.field) | ||||
| 	free(instance) | ||||
| } | ||||
| */ | ||||
| pub fn (instance BitField) getbit(bitnr int) int { | ||||
| 	if bitnr >= instance.size {return 0} | ||||
| 	return bitget(instance, bitnr) | ||||
| } | ||||
| 
 | ||||
| pub fn (instance mut BitField) setbit(bitnr int) { | ||||
| 	if bitnr >= instance.size {return} | ||||
| 	bitset(instance, bitnr) | ||||
| } | ||||
| 
 | ||||
| pub fn (instance mut BitField) clearbit(bitnr int) { | ||||
| 	if bitnr >= instance.size {return} | ||||
| 	bitclear(instance, bitnr) | ||||
| } | ||||
| 
 | ||||
| pub fn (instance mut BitField) togglebit(bitnr int) { | ||||
| 	if bitnr >= instance.size {return} | ||||
| 	bittoggle(instance, bitnr) | ||||
| } | ||||
| 
 | ||||
| pub fn bfand(input1 BitField, input2 BitField) BitField { | ||||
| 	size := min(input1.size, input2.size) | ||||
| 	bitnslots := bitnslots(size) | ||||
| 	mut output := new(size) | ||||
| 	mut i := 0 | ||||
| 	for i < bitnslots { | ||||
| 		output.field[i] = input1.field[i] & input2.field[i] | ||||
| 		i++ | ||||
| 	} | ||||
| 	cleartail(output) | ||||
| 	return output | ||||
| } | ||||
| 
 | ||||
| pub fn bfnot(input BitField) BitField { | ||||
| 	size := input.size | ||||
| 	bitnslots := bitnslots(size) | ||||
| 	mut output := new(size) | ||||
| 	mut i := 0 | ||||
| 	for i < bitnslots { | ||||
| 		output.field[i] = ~input.field[i] | ||||
| 		i++ | ||||
| 	} | ||||
| 	cleartail(output) | ||||
| 	return output | ||||
| } | ||||
| 
 | ||||
| pub fn bfor(input1 BitField, input2 BitField) BitField { | ||||
| 	size := min(input1.size, input2.size) | ||||
| 	bitnslots := bitnslots(size) | ||||
| 	mut output := new(size) | ||||
| 	mut i := 0 | ||||
| 	for i < bitnslots { | ||||
| 		output.field[i] = input1.field[i] | input2.field[i] | ||||
| 		i++ | ||||
| 	} | ||||
| 	cleartail(output) | ||||
| 	return output | ||||
| } | ||||
| 
 | ||||
| pub fn bfxor(input1 BitField, input2 BitField) BitField { | ||||
| 	size := min(input1.size, input2.size) | ||||
| 	bitnslots := bitnslots(size) | ||||
| 	mut output := new(size) | ||||
| 	mut i := 0 | ||||
| 	for i < bitnslots { | ||||
| 		output.field[i] = input1.field[i] ^ input2.field[i] | ||||
| 		i++ | ||||
| 	} | ||||
| 	cleartail(output) | ||||
| 	return output | ||||
| } | ||||
| 
 | ||||
| pub fn print(instance BitField) { | ||||
| 	mut i := 0 | ||||
| 	for i < instance.size { | ||||
| 		if instance.getbit(i) == 1 { | ||||
| 			print('1') | ||||
| 		} | ||||
| 		else { | ||||
| 			print('0') | ||||
| 		} | ||||
| 		i++ | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (instance BitField) getsize() int { | ||||
| 	return instance.size | ||||
| } | ||||
| 
 | ||||
| pub fn clone(input BitField) BitField { | ||||
| 	bitnslots := bitnslots(input.size) | ||||
| 	mut output := new(input.size) | ||||
| 	mut i := 0 | ||||
| 	for i < bitnslots { | ||||
| 		output.field[i] = input.field[i] | ||||
| 		i++ | ||||
| 	} | ||||
| 	return output | ||||
| } | ||||
|  | @ -0,0 +1,45 @@ | |||
| import bf | ||||
| 
 | ||||
| import rand | ||||
| 
 | ||||
| fn test_bf_new_size() { | ||||
| 	instance := bf.new(5) | ||||
| 	assert instance.getsize() == 5 | ||||
| } | ||||
| 
 | ||||
| fn test_bf_set_clear_toggle_get() { | ||||
| 	mut instance := bf.new(5) | ||||
| 	instance.setbit(4) | ||||
| 	assert instance.getbit(4) == 1 | ||||
| 	instance.clearbit(4) | ||||
| 	assert instance.getbit(4) == 0 | ||||
| 	instance.togglebit(4) | ||||
| 	assert instance.getbit(4) == 1 | ||||
| } | ||||
| 
 | ||||
| fn test_bf_and_not_or_xor() { | ||||
| 	rand.seed() | ||||
| 	len := 80 | ||||
| 	mut input1 := bf.new(len) | ||||
| 	mut input2 := bf.new(len) | ||||
| 	mut i := 0 | ||||
| 	for i < len { | ||||
| 		if rand.next(2) == 1 { | ||||
| 			input1.setbit(i) | ||||
| 		} | ||||
| 		if rand.next(2) == 1{ | ||||
| 			input2.setbit(i) | ||||
| 		} | ||||
| 		i++ | ||||
| 	} | ||||
| 	output1 := bf.bfxor(input1, input2) | ||||
| 	bfand := bf.bfand(input1, input2) | ||||
| 	bfor := bf.bfor(input1, input2) | ||||
| 	bfnot := bf.bfnot(bfand) | ||||
| 	output2 := bf.bfand(bfor, bfnot) | ||||
| 	mut result := 1 | ||||
| 	for i < len { | ||||
| 		if output1.getbit(i) != output2.getbit(i) {result = 0} | ||||
| 	} | ||||
| 	assert result == 1 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue