1 module tagion.utils.Gene; 2 3 import std.algorithm.iteration : fold; 4 import std.range : lockstep; 5 6 @nogc @safe 7 uint gene_count(const ulong bitstring) pure nothrow { 8 static uint count_ones(ulong BITS = ulong.sizeof * 8)(const ulong x) pure nothrow { 9 static if (BITS == 1) { 10 return x & 0x1; 11 } 12 else if (x == 0) { 13 return 0; 14 } 15 else { 16 enum HALF_BITS = BITS / 2; 17 enum MASK = ulong(1UL << (HALF_BITS)) - 1; 18 return count_ones!(HALF_BITS)(x & MASK) + count_ones!(HALF_BITS)(x >> HALF_BITS); 19 } 20 } 21 22 return count_ones(bitstring); 23 } 24 25 @safe 26 unittest { 27 enum SIZE_BITS = ulong.sizeof * 8; 28 { 29 const bits = cast(ulong) 0; 30 assert(bits.gene_count == 0); 31 } 32 { 33 const bits = cast(ulong) long(-1); 34 assert(bits.gene_count == SIZE_BITS); 35 } 36 { 37 const a_bits = ulong( 38 0b00001000_00010000_00000100_00100000_00000001_00001000_10000000_00000010UL); 39 const b_bits = ulong( 40 0b00101000_00010110_00100100_00100111_11110001_01001000_10011000_01100010); 41 assert(a_bits.gene_count == 8); 42 assert(b_bits.gene_count == 24); 43 } 44 } 45 46 @nogc @safe 47 uint gene_count(scope const(ulong[]) bitstream) pure nothrow { 48 return bitstream 49 .fold!((a, b) => a + gene_count(b))(uint(0)); 50 } 51 52 @safe 53 ulong[] gene_xor(scope const(ulong[]) a, scope const(ulong[]) b) pure nothrow { 54 auto result = new ulong[a.length]; 55 gene_xor(result, a, b); 56 return result; 57 } 58 59 @nogc @safe 60 void gene_xor(ref scope ulong[] result, scope const(ulong[]) a, scope const(ulong[]) b) pure nothrow 61 in { 62 assert(a.length == b.length); 63 assert(result.length == b.length, "Length of a and b should bed the same"); 64 } 65 do { 66 foreach (i, ref r; result) { 67 r = a[i] ^ b[i]; 68 } 69 } 70 71 @safe 72 unittest { 73 { 74 const a_bits = [0b01000001_01101101UL, 0b00010001_10011110UL]; 75 assert(a_bits.gene_count == 14); 76 const b_bits = [0b01011001_00010110UL, 0b01100101_10010011UL]; 77 assert(b_bits.gene_count == 15); 78 ulong[] result; 79 result.length = a_bits.length; 80 gene_xor(result, a_bits, b_bits); 81 assert(result == [0b00011000_01111011UL, 0b01110100_00001101]); 82 assert(result.gene_count == 15); 83 } 84 }