ref: 804ca7d4abe311fb94e02c8e1cd56aad8865a959
dir: /lib/std/bitset.myr/
use "alloc" use "die" use "extremum" use "hashfuncs" use "mk" use "slcp" use "sldup" use "slfill" use "traits" use "types" pkg std = type bitset = struct bits : size[:] ;; const mkbs : (-> bitset#) const bsdup : (bs : bitset# -> bitset#) const bsfree : (bs : bitset# -> void) const bsclear : (bs : bitset# -> bitset#) const bsmax : (a : bitset# -> size) const bscount : (a : bitset# -> size) generic bsput : (bs : bitset#, v : @a::(integral,numeric) -> bool) generic bsdel : (bs : bitset#, v : @a::(integral,numeric) -> bool) generic bshas : (bs : bitset#, v : @a::(integral,numeric) -> bool) const bsdiff : (a : bitset#, b : bitset# -> void) const bsintersect : (a : bitset#, b : bitset# -> void) const bsunion : (a : bitset#, b : bitset# -> void) const bsissubset : (a : bitset#, b : bitset# -> bool) impl equatable bitset# impl hashable bitset# type bsiter = struct idx : size bs : bitset# ;; impl iterable bsiter -> size const bybsvalue : (bs : bitset# -> bsiter) ;; const mkbs = { -> zalloc() } const bsdup = {bs -> mk([.bits=sldup(bs.bits)]) } const bsfree = {bs slfree(bs.bits) free(bs) } const bsclear = {bs slfill(bs.bits, 0) -> bs } const bsmax = {bs -> bs.bits.len * sizeof(size) * 8 } const bscount = {bs var n n = 0 for v : bybsvalue(bs) n++ ;; -> n } generic bsput = {bs, v var idx, off, changed idx = (v : size) / (8*sizeof(size)) off = (v : size) % (8*sizeof(size)) ensurelen(bs, idx) changed = (bs.bits[idx] & (1 << off)) == 0 bs.bits[idx] |= (1 << off) -> changed } generic bsdel = {bs, v var idx, off, changed changed = false idx = (v : size) / (8*sizeof(size)) off = (v : size) % (8*sizeof(size)) if idx < bs.bits.len changed = (bs.bits[idx] & (1 << off)) != 0 bs.bits[idx] &= ~(1 << off) ;; -> changed } generic bshas = {bs, v var idx var off idx = (v : size) / (8*sizeof(size)) off = (v : size) % (8*sizeof(size)) if idx >= bs.bits.len -> false ;; -> (bs.bits[idx] & (1 << off)) != 0 } const bsunion = {a, b eqsz(a, b) for var i = 0; i < b.bits.len; i++ a.bits[i] |= b.bits[i] ;; } const bsintersect = {a, b var n n = min(a.bits.len, b.bits.len) for var i = 0; i < n; i++ a.bits[i] &= b.bits[i] ;; } const bsdiff = {a, b var n n = min(b.bits.len, a.bits.len) for var i = 0; i < n; i++ a.bits[i] &= ~b.bits[i] ;; } const bsissubset = {a, b eqsz(a, b); for var i = 0; i < a.bits.len; i++ if (b.bits[i] & a.bits[i]) != b.bits[i] -> false ;; ;; -> true } impl equatable bitset# = eq = {a, b eqsz(a, b) for var i = 0; i < a.bits.len; i++ if a.bits[i] != b.bits[i] -> false ;; ;; -> true } ;; impl hashable bitset# = hash = {a var end : size end = a.bits.len while end > 0 && a.bits[end - 1] == 0 end-- ;; -> std.hash(a.bits[:end]) } ;; const ensurelen = {bs, len if bs.bits.len <= len slzgrow(&bs.bits, len + 1) ;; } const eqsz = {a, b var sz sz = max(a.bits.len, b.bits.len) ensurelen(a, sz) ensurelen(b, sz) } const bybsvalue = {bs -> [.idx=0, .bs=bs] } impl iterable bsiter -> size = __iternext__ = {itp, valp var bs = itp.bs var n = bsmax(bs) for var i = itp.idx; i < n; i++ /* fast forward by whole chunks */ while i < n && bs.bits[i / (8*sizeof(size))] == 0 i = (i + 8*sizeof(size)) & ~(8*sizeof(size) - 1) ;; if bshas(bs, i) itp.idx = i + 1 valp# = i -> true ;; ;; itp.idx = n -> false } __iterfin__ = {itp, valp } ;;