1 module lincount; 2 3 struct LPCounter 4 { 5 import std.bitmanip: BitArray; 6 import std.uuid: UUID; 7 8 private BitArray map; 9 private size_t _length = 0; 10 11 @disable this(); 12 13 private void set(size_t index) 14 { 15 if(map[index] == false) 16 { 17 map[index] = true; 18 _length++; 19 } 20 } 21 22 this(size_t kilobytes) 23 { 24 map.length = 8 * 1024 * kilobytes; 25 _length = 0; 26 } 27 28 void put(uint data) 29 { 30 import lincount.internal: fmix; 31 set(cast(size_t)(fmix(data) % map.length)); 32 } 33 34 void put(ulong data) 35 { 36 import lincount.internal: fmix; 37 set(cast(size_t)(fmix(data) % map.length)); 38 } 39 40 void put(UUID data) 41 { 42 set(data.toHash % map.length); 43 } 44 45 void put(in void[] data) 46 { 47 //hashOf(data); 48 import std.digest.digest: digest; 49 import lincount.internal: MurmurHash3_x64_128; 50 auto hashed = cast(ulong[2])digest!MurmurHash3_x64_128(data); 51 set((hashed[0] ^ hashed[1]) % map.length); 52 } 53 54 ulong count() 55 { 56 import std.math: log, lround; 57 if(map.length > _length) 58 return lround(map.length * -log(real(map.length - _length) / map.length)); 59 else 60 return map.length; 61 } 62 63 //returns the size of the underlying BitArray in KB 64 @property size_t size() 65 { 66 return map.length() / (8 * 1024); 67 } 68 69 }