Make packing of states generate a list of candidates for first slot via numpy
authorNick Downing <downing.nick@gmail.com>
Mon, 23 Jul 2018 08:49:04 +0000 (18:49 +1000)
committerNick Downing <downing.nick@gmail.com>
Mon, 23 Jul 2018 08:49:04 +0000 (18:49 +1000)
flex_dfa.py

index 0bc311e..7ce9a35 100644 (file)
@@ -197,8 +197,8 @@ class FlexDFA:
     self.entries = numpy.full((0x200, 2), -1, numpy.int16) # nxt, chk
     self.entries[:0x101, :] = 0 # jam state just returns to jam state
     self.entries[0, 0] = eob_state # except for the EOB transition
-    entries_used = numpy.zeros(0x200, numpy.bool)
-    entries_used[:0x101] = True # account for the jam (don't care) state
+    entries_free = numpy.full(0x200, True, numpy.bool)
+    entries_free[:0x101] = False # account for the jam (don't care) state
     n_entries = 0x101
 
     # pack states in reverse order (larger distances first)
@@ -230,25 +230,29 @@ class FlexDFA:
           new_entries[:n_entries, :] = self.entries[:n_entries, :]
           self.entries = new_entries
 
-          # extend entries_used, copying only n_entries entries
-          new_entries_used = numpy.zeros(
-            (entries_used.shape[0] * 2,),
+          # extend entries_free, copying only n_entries entries
+          new_entries_free = numpy.full(
+            (entries_free.shape[0] * 2,),
+            True,
             numpy.bool
           )
-          new_entries_used[:n_entries] = entries_used[:n_entries]
-          entries_used = new_entries_used
+          new_entries_free[:n_entries] = entries_free[:n_entries]
+          entries_free = new_entries_free
 
         # find a suitable spot and store differences from default state
-        start_index = 0
-        while start_index < n_entries:
-          if not numpy.any(entries_used[indices + start_index]):
+        # generate a list of candidates via numpy for the first slot only
+        for start_index in numpy.nonzero(
+          entries_free[indices[0]:n_entries]
+        )[0]:
+          indices_offset = indices + start_index
+          if numpy.all(entries_free[indices_offset]):
             break
-          start_index += 1
-        self.entries[indices + start_index, 0] = (
-          transitions[state_todo, indices]
-        )
-        self.entries[indices + start_index, 1] = state_todo
-        entries_used[indices + start_index] = True
+        else:
+          start_index = n_entries
+          indices_offset = indices + start_index
+        self.entries[indices_offset, 0] = transitions[state_todo, indices]
+        self.entries[indices_offset, 1] = state_todo
+        entries_free[indices_offset] = False
         if n_entries < start_index + 0x101:
           n_entries = start_index + 0x101