From: Janne H. <jjh...@gm...> - 2007-04-08 17:36:38
|
Hi Pascal, Thanks for reporting the bug! There's a fix for this in the CVS now. I've also added your test case as a regression test in Extlib's testing suite so that it doesn't resurrect itself in the future. The bug indeed was in BitSet.enum. I completely rewrote it. The new implementation is somewhat longer but IMO easier to read. Old one (excuse my re-indentation): let enum t = let rec make n = let cur = ref n in let rec next() = let pos = !cur lsr log_int_size and delta = !cur land int_size in if pos >= t.len then raise Enum.No_more_elements; let x = bget t.data pos in let rec loop i = if i = 8 then next() else if x land (1 lsl i) = 0 then begin incr cur; loop (i+1) end else !cur in let b = loop delta in incr cur; b in Enum.make ~next ~count:(fun () -> partial_count t !cur) ~clone:(fun () -> make !cur) in make 0 New one: (* Find the first set bit in the bit array *) let find_first_set b n = (* TODO there are many ways to speed this up. Lookup table would be one way to speed this up. *) let find_lsb b = assert (b <> 0); let rec loop n = if b land (1 lsl n) <> 0 then n else loop (n+1) in loop 0 in let buf = b.data in let rec find_bit byte_ndx bit_offs = if byte_ndx >= b.len then None else let byte = (bget buf byte_ndx) lsr bit_offs in if byte = 0 then find_bit (byte_ndx + 1) 0 else Some ((find_lsb byte) + (byte_ndx lsl log_int_size) + bit_offs) in find_bit (n lsr log_int_size) (n land int_size) let enum t = let rec make n = let cur = ref n in let rec next () = match find_first_set t !cur with Some elem -> cur := (elem+1); elem | None -> raise Enum.No_more_elements in Enum.make ~next ~count:(fun () -> partial_count t !cur) ~clone:(fun () -> make !cur) in make 0 Performance of the new implementation should be pretty much the same speed as the old one. Janne On 2/26/07, Pascal Zimmer <pas...@gm...> wrote: > I think this does qualify as a bug: > > # let b = BitSet.empty ();; > val b : BitSet.t = <abstr> > # BitSet.set b 8;; > - : unit = () > # BitSet.set b 9;; > - : unit = () > # let e = BitSet.enum b;; > val e : int Enum.t = <abstr> > # Enum.get e;; > - : int option = Some 8 > # Enum.get e;; > - : int option = None > > It seems to get triggered when consecutive numbers are stored and > retrieved from the bitset, although not every pair of numbers works. I > did not look into the details of BitSet.enum, but the bug is likely to > be there. > > Pascal > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys-and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > ocaml-lib-devel mailing list > oca...@li... > https://lists.sourceforge.net/lists/listinfo/ocaml-lib-devel > |